return normal;
}
+//
+// Returns the orientation of the points when traversed in order (from p1 to
+// p2 to p3). +1 = CCW, -1 = CW, 0 = colinear
+//
+int Geometry::Orientation(Point p1, Point p2, Point p3)
+{
+ double xx = p2.x - p1.x, yy = p2.y - p1.y;
+ double aa = p3.x - p1.x, bb = p3.y - p1.y;
+
+ // Mult by -1 if screen coords already transformed
+ double zz = (xx * bb) - (yy * aa);
+
+ return (zz < 0 ? -1 : (zz == 0 ? 0 : 1));
+}
+
Circle Geometry::FindCircleForThreePoints(Point p1, Point p2, Point p3)
{
// We use matrices and determinants to find the center and radius of the
return c;
}
+Arc Geometry::FindArcForThreePoints(Point p1, Point p2, Point p3)
+{
+ int orientation = Orientation(p1, p2, p3);
+
+ // Sanity check: if points are colinear, there is no arc
+ if (orientation == 0)
+ return Arc();
+
+ Circle c = FindCircleForThreePoints(p1, p2, p3);
+ double a1 = Vector::Angle(c.p[0], p1);
+ double a2 = Vector::Angle(c.p[0], p2);
+ double span = a2 - a1;
+
+ if (orientation < 0 && span > 0)
+ span -= TAU;
+ else if (orientation > 0 && span < 0)
+ span += TAU;
+
+ return Arc(c.p[0], c.radius[0], a1, span);
+}
+
double Geometry::Determinant3x3(double a11, double a12, double a13, double a21, double a22, double a23, double a31, double a32, double a33)
{
return (a11 * ((a22 * a33) - (a32 * a23)))
// N.B.: The radius can also be found with r = (a² + h²) / 2h where a is
// the 1/2 length of the line segment and h is the bump length.
-// double radius = (length + (1.0 / length)) / 2.0;
double radius = 0.5 * (((length * length) + (bumpLen * bumpLen)) / bumpLen);
Vector ctrVec = mpNormal * (radius - bumpLen);
Point center = midpoint + ctrVec;
return Arc(center, radius, angle1, span);
}
+
+double Geometry::Pack(Arc * a)
+{
+ Point p1 = a->p[0] + (Vector(cos(a->angle[0]), sin(a->angle[0])) * a->radius[0]);
+ Point p2 = a->p[0] + (Vector(cos(a->angle[0] + a->angle[1]), sin(a->angle[0] + a->angle[1])) * a->radius[0]);
+ double endpointLen = Vector::Magnitude(p1, p2) / 2.0;
+
+ // Bump height can be found with h = r ± sqr(r² - a²) where r is the
+ // radius, and a is the 1/2 length of the endpoint's line segment. The
+ // plus/minus term is positive if the arc span is less than 1/2 TAU,
+ // negative if the arc span is greater than 1/2 TAU.
+ double discriminant = sqrt((a->radius[0] * a->radius[0]) - (endpointLen * endpointLen));
+ double bumpLen = a->radius[0] + (discriminant * (fabs(a->angle[1]) < HALF_TAU ? 1.0 : -1.0));
+
+ return (bumpLen / endpointLen) * (a->angle[1] > 0 ? -1.0 : 1.0);
+}