Were’s the code for addcurve. Note that there’s a new parameter “first” which is true if the segment being added is the very first segment of the circle. It’s pretty obvious how to use it, and I won’t go back and show you how to back-fit it.

One important thing, however, is that there was a bit of instability in the “chop 90 dgerees off” algorithm. The fix is:

// are we in the first quadrant?
if (acos >= -1e-6 && acos90 >= 0) {
// a fudge factor. The algorithm is ok with angles slightly
// more than 90, but not with negative ones.
break;
}

Also, somehow I managed to mix up the two control points during the final rotation into place. not sure how, but the fix seems to work. The result is damn close to the java “Arc2D” result. One pixel off, at most.

private static void arc_addcurve(GeneralPath pp, Point2D.Double c, double r, Point2D.Double p1hat,
Point2D.Double p2hat, boolean first) {
// find midpoint
midp2.setLocation((p1hat.x + p2hat.x) / 2, (p1hat.y + p2hat.y) / 2);
hat(midp2, midp2hat);
// construct vector 90 degress clockwise from midp.
midp290hat.x = -midp2hat.y;
midp290hat.y = midp2hat.x;
// projection of p1hat onto midphat gives us cos
final double cosTheta = p1hat.x * midp2hat.x + p1hat.y * midp2hat.y;
// projection of p1hat onto midp90hat gives us -sin
final double sinTheta = -(p1hat.x * midp290hat.x + p1hat.y * midp290hat.y);
// at which point, we apply the solution directly out of wikipedia
final double x2_1 = (4 - cosTheta) / 3;
final double y2_1 = (1 - cosTheta) * (3 - cosTheta) / 3 / sinTheta;
final double x3_1 = x2_1;
final double y3_1 = -y2_1;
// rotate by midphat to get the final control point vectors
// I am not at all certain how I managed to scramble this,
// but it seems to work now.
final double x3 = x2_1 * midp2hat.x - y2_1 * midp2hat.y;
final double y3 = y2_1 * midp2hat.x + x2_1 * midp2hat.y;
final double x2 = x3_1 * midp2hat.x - y3_1 * midp2hat.y;
final double y2 = y3_1 * midp2hat.x + x3_1 * midp2hat.y;
// and draw the cubic!
if (first) {
pp.lineTo(c.x + p1hat.x * r, c.y + p1hat.y * r);
}
pp.curveTo(c.x + x2 * r, c.y + y2 * r, //
c.x + x3 * r, c.y + y3 * r, //
c.x + p2hat.x * r, c.y + p2hat.y * r);
}

This entry was posted on Sunday, January 1st, 2012 at 6:40 am and is filed under Java. You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.