+Point Geometry::GetPointForParameter(Object * obj, double t)
+{
+ if (obj->type == OTLine)
+ {
+ // Translate line vector to the origin, then add the scaled vector to
+ // initial point of the line.
+ Vector v = obj->p[1] - obj->p[0];
+ return obj->p[0] + (v * t);
+ }
+
+ return Point(0, 0);
+}
+
+Point Geometry::Midpoint(Line * line)
+{
+ return Point((line->p[0].x + line->p[1].x) / 2.0,
+ (line->p[0].y + line->p[1].y) / 2.0);
+}
+
+/*
+How to find the tangent of a point off a circle:
+
+ • Calculate the midpoint of the point and the center of the circle
+ • Get the length of the line segment from point and the center divided by two
+ • Use that length to construct a circle with the point at the center and the
+ radius equal to that length
+ • The intersection of the two circles are the tangent points
+
+Another way:
+
+ • Find angle between radius and line between point and center
+ • Angle +/- from line (point to center) are the tangent points
+
+*/
+void Geometry::FindTangents(Object * c, Point p)
+{
+ // Set up global vars
+ Global::numIntersectPoints = Global::numIntersectParams = 0;
+
+ // Get the distance between the point and the center of the circle, the
+ // length, and the angle.
+ Vector centerLine(c->p[0], p);
+ double d = centerLine.Magnitude();
+ double clAngle = centerLine.Angle();
+
+ // If the point is on or inside the circle, there are no tangents.
+ if (d <= c->radius[0])
+ return;
+
+ // Use 'cos(a) = adjacent / hypotenuse' to get the tangent angle
+ double a = acos(c->radius[0] / d);
+
+ // Finally, find the points of intersection by using +/- the angle found
+ // from the centerline's angle
+ Global::intersectPoint[0].x = c->p[0].x + (cos(clAngle + a) * c->radius[0]);
+ Global::intersectPoint[0].y = c->p[0].y + (sin(clAngle + a) * c->radius[0]);
+ Global::intersectPoint[1].x = c->p[0].x + (cos(clAngle - a) * c->radius[0]);
+ Global::intersectPoint[1].y = c->p[0].y + (sin(clAngle - a) * c->radius[0]);
+ Global::numIntersectPoints = 2;
+}
+
+/*
+The extangents can be found by collapsing the circle of smaller radius to a point, and diminishing the larger circle by the radius of the smaller, then treating it like the point-circle case (you have to translate the tangent back out by the length of the radius of the smaller circle once found).
+
+Not sure what the analogous method for finding the intangents are... :-/
+Looks like the intangent can be found by augmenting the larger circle by the smaller radius, and doing the center of the smaller as the point-circle case again, only translating the line back by the radius of the smaller.
+*/
+void Geometry::FindTangents(Object * c1, Object * c2)
+{
+ // Set up global vars
+ Global::numIntersectPoints = Global::numIntersectParams = 0;
+
+ // Find the larger and smaller of the two:
+ Object * cLg = c1, * cSm = c2;
+
+ if (c2->radius[0] > c1->radius[0])
+ cLg = c2, cSm = c1;
+
+ // Get the distance between the point and the center of the circle, the
+ // length, and the angle.
+ Vector centerLine(cLg->p[0], cSm->p[0]);
+ double d = centerLine.Magnitude();
+ double clAngle = centerLine.Angle();
+
+ // If one circle is completely inside the other, there are no tangents.
+ if ((d + cSm->radius[0]) <= cLg->radius[0])
+ return;
+
+ // Subtract the radius of the smaller from the larger, and use the point-circle method to find the extangent:
+ double a = acos((cLg->radius[0] - cSm->radius[0]) / d);
+
+ // Finally, find the points of intersection by using +/- the angle found
+ // from the centerline's angle
+ Global::intersectPoint[0].x = cLg->p[0].x + (cos(clAngle + a) * cLg->radius[0]);
+ Global::intersectPoint[0].y = cLg->p[0].y + (sin(clAngle + a) * cLg->radius[0]);
+ Global::intersectPoint[1].x = cSm->p[0].x + (cos(clAngle + a) * cSm->radius[0]);
+ Global::intersectPoint[1].y = cSm->p[0].y + (sin(clAngle + a) * cSm->radius[0]);
+
+ Global::intersectPoint[2].x = cLg->p[0].x + (cos(clAngle - a) * cLg->radius[0]);
+ Global::intersectPoint[2].y = cLg->p[0].y + (sin(clAngle - a) * cLg->radius[0]);
+ Global::intersectPoint[3].x = cSm->p[0].x + (cos(clAngle - a) * cSm->radius[0]);
+ Global::intersectPoint[3].y = cSm->p[0].y + (sin(clAngle - a) * cSm->radius[0]);
+ Global::numIntersectPoints = 4;
+
+ // If the circles overlap, there are no intangents.
+ if (d <= (cLg->radius[0] + cSm->radius[0]))
+ return;
+
+ // Add the radius of the smaller from the larger, and use the point-circle method to find the intangent:
+ a = acos((cLg->radius[0] + cSm->radius[0]) / d);
+
+ // Finally, find the points of intersection by using +/- the angle found
+ // from the centerline's angle
+ Global::intersectPoint[4].x = cLg->p[0].x + (cos(clAngle + a) * cLg->radius[0]);
+ Global::intersectPoint[4].y = cLg->p[0].y + (sin(clAngle + a) * cLg->radius[0]);
+ Global::intersectPoint[5].x = cSm->p[0].x + (cos(clAngle - a) * cSm->radius[0]);
+ Global::intersectPoint[5].y = cSm->p[0].y + (sin(clAngle - a) * cSm->radius[0]);
+
+ Global::intersectPoint[6].x = cLg->p[0].x + (cos(clAngle - a) * cLg->radius[0]);
+ Global::intersectPoint[6].y = cLg->p[0].y + (sin(clAngle - a) * cLg->radius[0]);
+ Global::intersectPoint[7].x = cSm->p[0].x + (cos(clAngle + a) * cSm->radius[0]);
+ Global::intersectPoint[7].y = cSm->p[0].y + (sin(clAngle + a) * cSm->radius[0]);
+ Global::numIntersectPoints = 8;
+}
+
+//
+// Parameter 1: point in question
+// Parameter 2, 3: points we are comparing to
+//
+Point Geometry::NearestTo(Point point, Point p1, Point p2)
+{
+ double l1 = Vector::Magnitude(point, p1);
+ double l2 = Vector::Magnitude(point, p2);
+
+ return (l1 < l2 ? p1 : p2);
+}