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); } } }
void spiro_to_bpath(const spiro_seg *s, int n, bezctx *bc) { int i; int nsegs = s[n - 1].ty == '}' ? n - 1 : n; for (i = 0; i < nsegs; i++) { double x0 = s[i].x; double y0 = s[i].y; double x1 = s[i + 1].x; double y1 = s[i + 1].y; if (i == 0) bezctx_moveto(bc, x0, y0, s[0].ty == '{'); bezctx_mark_knot(bc, i); spiro_seg_to_bpath(s[i].ks, x0, y0, x1, y1, bc, 0); } }
void spiro_to_bpath(const spiro_seg *s, int n, bezctx *bc) { int i, nsegs; double x0, y0, x1, y1; if (s==NULL || n <= 0 || bc==NULL) return; nsegs = s[n - 1].ty == '}' ? n - 1 : n; for (i = 0; i < nsegs; i++) { x0 = s[i].x; x1 = s[i + 1].x; y0 = s[i].y; y1 = s[i + 1].y; if (i == 0) bezctx_moveto(bc, x0, y0, s[0].ty == '{'); bezctx_mark_knot(bc, i); spiro_seg_to_bpath(s[i].ks, x0, y0, x1, y1, bc, 0); } }