Exemple #1
0
/*
 * Convert cubic Bezier curve control points to polyline
 * vertices.  Leaves the last vertex off, so you can continue
 * with another curve.
 */
static void
bpts1(Plist *l, Point p0, Point p1, Point p2, Point p3, int scale)
{
	Point p01, p12, p23, p012, p123, p0123;
	Point tp0, tp1, tp2, tp3;
	tp0=divpt(p0, scale);
	tp1=divpt(p1, scale);
	tp2=divpt(p2, scale);
	tp3=divpt(p3, scale);
	if(psdist(tp1, tp0, tp3)<=1 && psdist(tp2, tp0, tp3)<=1){
		appendpt(l, tp0);
		appendpt(l, tp1);
		appendpt(l, tp2);
	}
	else{
		/*
		 * if scale factor is getting too big for comfort,
		 * rescale now & concede the rounding error
		 */
		if(scale>(1<<12)){
			p0=tp0;
			p1=tp1;
			p2=tp2;
			p3=tp3;
			scale=1;
		}
		p01=addpt(p0, p1);
		p12=addpt(p1, p2);
		p23=addpt(p2, p3);
		p012=addpt(p01, p12);
		p123=addpt(p12, p23);
		p0123=addpt(p012, p123);
		bpts1(l, mulpt(p0, 8), mulpt(p01, 4), mulpt(p012, 2), p0123, scale*8);
		bpts1(l, p0123, mulpt(p123, 2), mulpt(p23, 4), mulpt(p3, 8), scale*8);
	}
}
Exemple #2
0
static void
_bezsplinepts(Plist *l, Point *pt, int npt)
{
	Point *p, *ep;
	Point a, b, c, d;
	int periodic;

	if(npt<3)
		return;
	ep = &pt[npt-3];
	periodic = eqpt(pt[0], ep[2]);
	if(periodic){
		a = divpt(addpt(ep[1], pt[0]), 2);
		b = divpt(addpt(ep[1], mulpt(pt[0], 5)), 6);
		c = divpt(addpt(mulpt(pt[0], 5), pt[1]), 6);
		d = divpt(addpt(pt[0], pt[1]), 2);
		bpts(l, a, b, c, d);
	}
	for(p=pt; p<=ep; p++){
		if(p==pt && !periodic){
			a = p[0];
			b = divpt(addpt(p[0], mulpt(p[1], 2)), 3);
		}
		else{
			a = divpt(addpt(p[0], p[1]), 2);
			b = divpt(addpt(p[0], mulpt(p[1], 5)), 6);
		}
		if(p==ep && !periodic){
			c = divpt(addpt(mulpt(p[1], 2), p[2]), 3);
			d = p[2];
		}
		else{
			c = divpt(addpt(mulpt(p[1], 5), p[2]), 6);
			d = divpt(addpt(p[1], p[2]), 2);
		}
		bpts(l, a, b, c, d);
	}
	appendpt(l, d);
}
Exemple #3
0
static void
bezierpts(Plist *l, Point p0, Point p1, Point p2, Point p3)
{
	bpts(l, p0, p1, p2, p3);
	appendpt(l, p3);
}
Exemple #4
0
/* append:
 */
static int 
append(path * path, int bi, point p0, point p1, int polysz)
{
    point v[8];		/* worst case 4 corners + 2 segs * 2 points each */
    point w[8];
    box b = path->boxes[bi];
    box bb;
    int i, i0, npw, delta;
    point q0 = { 0, 0 }, q1 = { 0, 0}, r;
    int pn;

    /* v = 4 corners of b, p0 and p1 */
    pn = 0;
    v[pn++] = b.LL;
    v[pn++] = mkpt(b.UR.x, b.LL.y);
    v[pn++] = b.UR;
    v[pn++] = mkpt(b.LL.x, b.UR.y);
    v[pn++] = p0;
    v[pn++] = p1;

    if (bi + 1 < path->nbox) {
	bb = path->boxes[bi + 1];
	/* determine points q0,q1 where b and bb touch and append to v */
	if (b.UR.x == bb.LL.x) {
	    q0.x = q1.x = b.UR.x;
	    q0.y = MIN(b.UR.y, bb.UR.y);
	    q1.y = MAX(b.LL.y, bb.LL.y);
	} else if (b.LL.x == bb.UR.x) {
	    q0.x = q1.x = b.LL.x;
	    q0.y = MIN(b.UR.y, bb.UR.y);
	    q1.y = MAX(b.LL.y, bb.LL.y);
	} else if (b.UR.y == bb.LL.y) {
	    q0.y = q1.y = b.UR.y;
	    q0.x = MIN(b.UR.x, bb.UR.x);
	    q1.x = MAX(b.LL.x, bb.LL.x);
	} else if (b.LL.y == bb.UR.y) {
	    q0.y = q1.y = b.LL.y;
	    q0.x = MIN(b.UR.x, bb.UR.x);
	    q1.x = MAX(b.LL.x, bb.LL.x);
	} else
	    abort();
	v[pn++] = q0;
	v[pn++] = q1;
    }

    /* sort v so that the cyclic order is p0, all other points, p1  */
    B = b;
    qsort(v, pn, sizeof(v[0]), cmpf);

    /* eliminate duplicates and record i0 = index of p0 in w */
    w[0] = v[0];
    npw = 1;
    i0 = -1;
    for (i = 0; i < pn; i++) {
	if (pteq(w[npw - 1], p0))
	    i0 = npw - 1;
	if (!pteq(v[i], w[npw - 1]))
	    w[npw++] = v[i];
    }

    i = i0;
    if (bi == 0)
	polysz = appendpt(p0, polysz);
    if (pteq(p1, w[(i0 + 1) % npw]))
	delta = -1;
    else if (pteq(p1, w[(i0 - 1 + npw) % npw]))
	delta = 1;
    else
	abort();
    do {
	i = (i + delta + npw) % npw;	/* go to the next point in order */
	r = w[i];		/* call it r */

	/* append r to current poly, except p0 and p1 are special cases */
	if ((bi == 0) || (!pteq(r, p0) && !pteq(r, p1)))
	    polysz = appendpt(r, polysz);
	if (pteq(r, p1))
	    break;
	if (bi + 1 < path->nbox) {	/* recur when we hit the next box */
	    if (pteq(r, q0)) {
		polysz = append(path, bi + 1, q0, q1, polysz);
		polysz = appendpt(q1, polysz);	/* assumes q1 != p0 and p1 */
		i += delta;	/* skip q1 */
	    } else if (pteq(r, q1)) {
		polysz = append(path, bi + 1, q1, q0, polysz);
		polysz = appendpt(q0, polysz);
		i += delta;
	    }
	}
    } while (i != i0);
    return polysz;
}