X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fgeometry.cpp;h=82d24e84c492ca81e2f116b23b1d84d14fc53d1a;hb=dacd9dc2c1ac093e4945f7befaeb5ff1801a0f52;hp=f4918560990d8ddcd61709daf54aae49c6b4fadc;hpb=10cf4c797bed05831e976068b7504908279dc997;p=architektonas diff --git a/src/geometry.cpp b/src/geometry.cpp index f491856..82d24e8 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -525,6 +525,21 @@ Vector Geometry::GetNormalOfPointAndLine(Point p, Line * l) 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 @@ -582,6 +597,27 @@ Circle Geometry::FindCircleForThreePoints(Point p1, Point p2, Point p3) 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))) @@ -602,7 +638,6 @@ Arc Geometry::Unpack(Point tail, Point head, double bump) // 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; @@ -621,3 +656,19 @@ Arc Geometry::Unpack(Point tail, Point head, double bump) 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); +}