Example #1
0
static void
spiro_seg_to_bpath(const double ks[4],
		   double x0, double y0, double x1, double y1,
		   bezctx *bc, int depth)
{
    double bend = fabs(ks[0]) + fabs(.5 * ks[1]) + fabs(.125 * ks[2]) +
	fabs((1./48) * ks[3]);

    if (!bend > 1e-8) {
	bezctx_lineto(bc, x1, y1);
    } else {
	double seg_ch = hypot(x1 - x0, y1 - y0);
	double seg_th = atan2(y1 - y0, x1 - x0);
	double xy[2];
	double ch, th;
	double scale, rot;
	double th_even, th_odd;
	double ul, vl;
	double ur, vr;

	integrate_spiro(ks, xy);
	ch = hypot(xy[0], xy[1]);
	th = atan2(xy[1], xy[0]);
	scale = seg_ch / ch;
	rot = seg_th - th;
	if (depth > 5 || bend < 1.) {
	    th_even = (1./384) * ks[3] + (1./8) * ks[1] + rot;
	    th_odd = (1./48) * ks[2] + .5 * ks[0];
	    ul = (scale * (1./3)) * cos(th_even - th_odd);
	    vl = (scale * (1./3)) * sin(th_even - th_odd);
	    ur = (scale * (1./3)) * cos(th_even + th_odd);
	    vr = (scale * (1./3)) * sin(th_even + th_odd);
	    bezctx_curveto(bc, x0 + ul, y0 + vl, x1 - ur, y1 - vr, x1, y1);
	} else {
	    /* subdivide */
	    double ksub[4];
	    double thsub;
	    double xysub[2];
	    double xmid, ymid;
	    double cth, sth;

	    ksub[0] = .5 * ks[0] - .125 * ks[1] + (1./64) * ks[2] - (1./768) * ks[3];
	    ksub[1] = .25 * ks[1] - (1./16) * ks[2] + (1./128) * ks[3];
	    ksub[2] = .125 * ks[2] - (1./32) * ks[3];
	    ksub[3] = (1./16) * ks[3];
	    thsub = rot - .25 * ks[0] + (1./32) * ks[1] - (1./384) * ks[2] + (1./6144) * ks[3];
	    cth = .5 * scale * cos(thsub);
	    sth = .5 * scale * sin(thsub);
	    integrate_spiro(ksub, xysub);
	    xmid = x0 + cth * xysub[0] - sth * xysub[1];
	    ymid = y0 + cth * xysub[1] + sth * xysub[0];
	    spiro_seg_to_bpath(ksub, x0, y0, xmid, ymid, bc, depth + 1);
	    ksub[0] += .25 * ks[1] + (1./384) * ks[3];
	    ksub[1] += .125 * ks[2];
	    ksub[2] += (1./16) * ks[3];
	    spiro_seg_to_bpath(ksub, xmid, ymid, x1, y1, bc, depth + 1);
	}
    }
}
Example #2
0
int
test_integ(void) {
    double ks[] = {1, 2, 3, 4};
    double xy[2];
    double xynom[2];
    double ch, th;
    int i, j;
    int nsubdiv;

    n = ORDER < 6 ? 4096 : 1024;
    integrate_spiro(ks, xynom);
    nsubdiv = ORDER < 12 ? 8 : 7;
    for (i = 0; i < nsubdiv; i++) {
	double st, en;
	double err;
	int n_iter = (1 << (20 - i));

	n = 1 << i;
	st = get_time();
	for (j = 0; j < n_iter; j++)
	    integrate_spiro(ks, xy);
	en = get_time();
	err = hypot(xy[0] - xynom[0], xy[1] - xynom[1]);
#ifdef VERBOSE
	printf("%d %d %g %g\n", ORDER, n, (en - st) / n_iter, err);
#endif
	ch = hypot(xy[0], xy[1]);
	th = atan2(xy[1], xy[0]);
#if 0
	printf("n = %d: integ(%g %g %g %g) = %g %g, ch = %g, th = %g\n", n,
	       ks[0], ks[1], ks[2], ks[3], xy[0], xy[1], ch, th);
	printf("%d: %g %g\n", n, xy[0] - xynom[0], xy[1] - xynom[1]);
#endif
    }
    return 0;
}
Example #3
0
static double
compute_ends(const double ks[4], double ends[2][4], double seg_ch)
{
    double xy[2];
    double ch, th;
    double l, l2, l3;
    double th_even, th_odd;
    double k0_even, k0_odd;
    double k1_even, k1_odd;
    double k2_even, k2_odd;

    integrate_spiro(ks, xy, N_IS);
    ch = hypot(xy[0], xy[1]);
    th = atan2(xy[1], xy[0]);
    l = ch / seg_ch;

    th_even = .5 * ks[0] + (1./48) * ks[2];
    th_odd = .125 * ks[1] + (1./384) * ks[3] - th;
    ends[0][0] = th_even - th_odd;
    ends[1][0] = th_even + th_odd;
    k0_even = l * (ks[0] + .125 * ks[2]);
    k0_odd = l * (.5 * ks[1] + (1./48) * ks[3]);
    ends[0][1] = k0_even - k0_odd;
    ends[1][1] = k0_even + k0_odd;
    l2 = l * l;
    k1_even = l2 * (ks[1] + .125 * ks[3]);
    k1_odd = l2 * .5 * ks[2];
    ends[0][2] = k1_even - k1_odd;
    ends[1][2] = k1_even + k1_odd;
    l3 = l2 * l;
    k2_even = l3 * ks[2];
    k2_odd = l3 * .5 * ks[3];
    ends[0][3] = k2_even - k2_odd;
    ends[1][3] = k2_even + k2_odd;

    return l;
}
Example #4
0
static void
spiro_seg_to_bpath0(const double ks[4], double *dm,
		   double x0, double y0, double x1, double y1,
		   bezctx *bc, int ncq, int depth)
{
    double bend, seg_ch, seg_th, ch, th, scale, rot;
    double th_even, th_odd, ul, vl, ur, vr;
    double thsub, xmid, ymid, cth, sth;
    double ksub[4], xysub[2], xy[2];

    bend = fabs(ks[0]) + fabs(.5 * ks[1]) + fabs(.125 * ks[2]) +
	fabs((1./48) * ks[3]);

    if (bend <= 1e-8) {
	if (depth >= 0 || depth < -4) {
#ifdef VERBOSE
	    printf("...to next knot point...\n");
#endif
	    bezctx_lineto(bc, dm[3], dm[4]);
	} else {
	    bezctx_lineto(bc, (x1 * dm[0] + dm[1]), (y1 * dm[0] + dm[2]));
	}
    } else {
	seg_ch = hypot(x1 - x0, y1 - y0);
	seg_th = atan2(y1 - y0, x1 - x0);

	integrate_spiro(ks, xy, N_IS);
	ch = hypot(xy[0], xy[1]);
	th = atan2(xy[1], xy[0]);
	scale = seg_ch / ch;
	rot = seg_th - th;
	if (abs(depth) > 5 || bend < 1.) {
	    th_even = (1./384) * ks[3] + (1./8) * ks[1] + rot;
	    th_odd = (1./48) * ks[2] + .5 * ks[0];
	    ul = (scale * (1./3)) * cos(th_even - th_odd);
	    vl = (scale * (1./3)) * sin(th_even - th_odd);
	    ur = (scale * (1./3)) * cos(th_even + th_odd);
	    vr = (scale * (1./3)) * sin(th_even + th_odd);
	    if (depth >= 0 || depth < -4) {
#ifdef VERBOSE
		printf("...to next knot point...\n");
#endif
		bezctx_curveto(bc, ((x0 + ul) * dm[0] + dm[1]), ((y0 + vl) * dm[0] + dm[2]),
				((x1 - ur) * dm[0] + dm[1]), ((y1 - vr) * dm[0] + dm[2]),
				dm[3], dm[4]);
	    } else {
		bezctx_curveto(bc, ((x0 + ul) * dm[0] + dm[1]), ((y0 + vl) * dm[0] + dm[2]),
				((x1 - ur) * dm[0] + dm[1]), ((y1 - vr) * dm[0] + dm[2]),
				(x1 * dm[0] + dm[1]), (y1 * dm[0] + dm[2]));
	    }
	} else {
	    /* subdivide */
#ifdef VERBOSE
		printf("...subdivide curve...\n");
#endif
	    ksub[0] = .5 * ks[0] - .125 * ks[1] + (1./64) * ks[2] - (1./768) * ks[3];
	    ksub[1] = .25 * ks[1] - (1./16) * ks[2] + (1./128) * ks[3];
	    ksub[2] = .125 * ks[2] - (1./32) * ks[3];
	    ksub[3] = (1./16) * ks[3];
	    thsub = rot - .25 * ks[0] + (1./32) * ks[1] - (1./384) * ks[2] + (1./6144) * ks[3];
	    cth = .5 * scale * cos(thsub);
	    sth = .5 * scale * sin(thsub);
	    integrate_spiro(ksub, xysub, N_IS);
	    xmid = x0 + cth * xysub[0] - sth * xysub[1];
	    ymid = y0 + cth * xysub[1] + sth * xysub[0];
	    spiro_seg_to_bpath0(ksub, dm, x0, y0, xmid, ymid, bc, ncq, -(abs(depth) + 1));
	    ksub[0] += .25 * ks[1] + (1./384) * ks[3];
	    ksub[1] += .125 * ks[2];
	    ksub[2] += (1./16) * ks[3];
	    spiro_seg_to_bpath0(ksub, dm, xmid, ymid, x1, y1, bc, ncq, (depth >= 0 ? ++depth : --depth));
	}
    }
}
Example #5
0
void
print_seg(const double ks[4], double x0, double y0, double x1, double y1)
{
    double bend = fabs(ks[0]) + fabs(.5 * ks[1]) + fabs(.125 * ks[2]) +
	fabs((1./48) * ks[3]);

    if (bend < 1e-8) {
#ifdef VERBOSE
	printf("%g %g lineto\n", x1, y1);
#endif
    } else {
	double seg_ch = hypot(x1 - x0, y1 - y0);
	double seg_th = atan2(y1 - y0, x1 - x0);
	double xy[2];
	double ch, th;
	double scale, rot;
	double th_even, th_odd;
	double ul, vl;
	double ur, vr;

	integrate_spiro(ks, xy);
	ch = hypot(xy[0], xy[1]);
	th = atan2(xy[1], xy[0]);
	scale = seg_ch / ch;
	rot = seg_th - th;
	if (bend < 1.) {
	    th_even = (1./384) * ks[3] + (1./8) * ks[1] + rot;
	    th_odd = (1./48) * ks[2] + .5 * ks[0];
	    ul = (scale * (1./3)) * cos(th_even - th_odd);
	    vl = (scale * (1./3)) * sin(th_even - th_odd);
	    ur = (scale * (1./3)) * cos(th_even + th_odd);
	    vr = (scale * (1./3)) * sin(th_even + th_odd);
#ifdef VERBOSE
	    printf("%g %g %g %g %g %g curveto\n",
		   x0 + ul, y0 + vl, x1 - ur, y1 - vr, x1, y1);
#endif
	    
	} else {
	    /* subdivide */
	    double ksub[4];
	    double thsub;
	    double xysub[2];
	    double xmid, ymid;
	    double cth, sth;

	    ksub[0] = .5 * ks[0] - .125 * ks[1] + (1./64) * ks[2] - (1./768) * ks[3];
	    ksub[1] = .25 * ks[1] - (1./16) * ks[2] + (1./128) * ks[3];
	    ksub[2] = .125 * ks[2] - (1./32) * ks[3];
	    ksub[3] = (1./16) * ks[3];
	    thsub = rot - .25 * ks[0] + (1./32) * ks[1] - (1./384) * ks[2] + (1./6144) * ks[3];
	    cth = .5 * scale * cos(thsub);
	    sth = .5 * scale * sin(thsub);
	    integrate_spiro(ksub, xysub);
	    xmid = x0 + cth * xysub[0] - sth * xysub[1];
	    ymid = y0 + cth * xysub[1] + sth * xysub[0];
	    print_seg(ksub, x0, y0, xmid, ymid);
	    ksub[0] += .25 * ks[1] + (1./384) * ks[3];
	    ksub[1] += .125 * ks[2];
	    ksub[2] += (1./16) * ks[3];
	    print_seg(ksub, xmid, ymid, x1, y1);
	}
    }
}