+ hitPoint1 = hitPoint2 = hitLine = false;
+ Vector lineSegment = endpoint - position;
+ Vector v1 = point - position;
+ Vector v2 = point - endpoint;
+ double t = Vector::Parameter(position, endpoint, point);
+ double distance;
+
+ // Geometric interpretation:
+ // The parameter "t" on the vector lineSegment is where the normal of
+ // lineSegment coincides with point. If t < 0, the normal lies beyond the
+ // 1st endpoint. If t > 1, then the normal lies beyond the 2nd endpoint. We
+ // only calculate the length of the normal between the point and the
+ // lineSegment when the parameter is between 0 and 1.
+
+ // Geometric interpretation of "distance = ?Det?(ls, v1) / |ls|":
+ // If the segment endpoints are s and e, and the point is p, then the test
+ // for the perpendicular intercepting the segment is equivalent to insisting
+ // that the two dot products {s-e}.{s-p} and {e-s}.{e-p} are both non-negative.
+ // Perpendicular distance from the point to the segment is computed by first
+ // computing the area of the triangle the three points form, then dividing by
+ // the length of the segment. Distances are done just by the Pythagorean
+ // theorem. Twice the area of the triangle formed by three points is the
+ // determinant of the following matrix:
+ //
+ // sx sy 1 0 0 1 0 0 0
+ // ex ey 1 ==> ex ey 1 ==> ex ey 0
+ // px py 1 px py 1 px py 0
+ //
+ // By translating the start point to the origin, and subtracting row 1 from
+ // all other rows, we end up with the matrix on the right which greatly
+ // simplifies the calculation of the determinant.
+
+ if (t < 0.0)
+ distance = v1.Magnitude();
+ else if (t > 1.0)
+ distance = v2.Magnitude();
+ else
+ // distance = ?Det?(ls, v1) / |ls|
+ distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y)
+ / lineSegment.Magnitude());
+
+ if ((v1.Magnitude() * Painter::zoom) < 8.0)
+ hitPoint1 = true;
+ else if ((v2.Magnitude() * Painter::zoom) < 8.0)
+ hitPoint2 = true;
+ else if ((distance * Painter::zoom) < 5.0)
+ hitLine = true;
+
+ return (hitPoint1 || hitPoint2 || hitLine ? true : false);
+// return HitStateChanged();
+}
+
+
+// Check to see if the point passed in coincides with any we have. If so, return a
+// pointer to it; otherwise, return NULL.
+/*virtual*/ Vector * Line::GetPointAt(Vector v)
+{
+ if (v == position)
+ return &position;
+ else if (v == endpoint)
+ return &endpoint;
+
+ return 0;
+}
+
+
+/*virtual*/ void Line::Enumerate(FILE * file)
+{
+ fprintf(file, "LINE %i (%lf,%lf) (%lf,%lf)\n", layer, position.x, position.y, endpoint.x, endpoint.y);
+}
+
+
+/*virtual*/ Object * Line::Copy(void)
+{
+#warning "!!! This doesn't take care of attached Dimensions !!!"
+/*
+This is a real problem. While having a pointer in the Dimension to this line's points
+is fast & easy, it creates a huge problem when trying to replicate an object like this.
+
+Maybe a way to fix that then, is to have reference numbers instead of pointers. That
+way, if you copy them, ... you might still have problems. Because you can't be sure if
+a copy will be persistant or not, you then *definitely* do not want them to have the
+same reference number.
+*/
+ return new Line(position, endpoint, parent);
+}
+
+
+/*virtual*/ Vector Line::GetPointAtParameter(double parameter)
+{
+ if (parameter <= 0)
+ return position;
+ else if (parameter >= 1.0)
+ return endpoint;
+
+ // Our parameter lies between zero and one, so calculate it!
+ Vector v(endpoint, position);
+ double length = v.Magnitude();
+ // We scale the magnitude of v so that it lies between 0 and 1...
+ // By multiplying the parameter by the magnitude, we obtain the point we
+ // want. No scaling necessary as it's inherent in the approach!
+ double spotOnLength = length * parameter;
+
+ // To get our point, we use the initial point of the line and add in our
+ // scaled point.
+ Vector result = position + (v * spotOnLength);
+ return result;
+}
+
+
+/*virtual*/ QRectF Line::Extents(void)
+{
+ QRectF rect(QPointF(position.x, position.y), QPointF(endpoint.x, endpoint.y));
+ return rect.normalized();
+}
+
+
+/*virtual*/ void Line::Translate(Vector amount)
+{
+ position += amount;
+ endpoint += amount;
+}
+
+
+/*virtual*/ void Line::Rotate(Vector point, double angle)
+{
+}
+
+
+/*virtual*/ void Line::Scale(Vector point, double amount)
+{
+}
+
+
+/*virtual*/ Object * Line::Mirror(Vector p1, Vector p2)
+{
+#if 0
+ return NULL;
+
+double Vector::Parameter(Vector v1, Vector v2, Vector p)
+{
+ // Geometric interpretation:
+ // The parameterized point on the vector lineSegment is where the normal of
+ // the lineSegment to the point intersects lineSegment. If the pp < 0, then
+ // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the
+ // perpendicular lies beyond the 2nd endpoint.
+
+ Vector lineSegment = v2 - v1;
+ double magnitude = lineSegment.Magnitude();
+ Vector pointSegment = p - v1;
+ double t = lineSegment.Dot(pointSegment) / (magnitude * magnitude);
+ return t;
+}
+
+
+// Return the normal to the linesegment formed by the passed in points.
+// (Not sure which is head or tail, or which hand the normal lies)
+/*static*/ Vector Vector::Normal(Vector v1, Vector v2)
+#endif
+
+ double t1 = Vector::Parameter(p1, p2, position);
+ double t2 = Vector::Parameter(p1, p2, endpoint);
+
+ Vector unit = Vector(p1, p2).Unit();
+ Vector v1 = unit * t1;
+ Vector v2 = unit * t2;
+
+// Vector normal = Vector::Normal(p1, p2);
+ // Get the points normal to position & endpoint to the line passed in
+ // (these are tails)
+ Vector v3 = p1 + v1;
+ Vector v4 = p1 + v2;
+
+ // Make our mirrored vectors
+ Vector v5 = -(position - v3);
+ Vector v6 = -(endpoint - v4);
+
+ // Find the points
+ Vector v7 = v3 + v5;
+ Vector v8 = v4 + v6;
+
+ return new Line(v7, v8);
+}
+
+
+void Line::SetDimensionOnLine(Dimension * dimension/*=NULL*/)
+{
+ // If they don't pass one in, create it for the caller.
+ if (dimension == NULL)
+ {
+//printf("Line::SetDimensionOnLine(): Creating new dimension...\n");
+// dimension = new Dimension(position, endpoint, DTLinear, this);
+ dimension = new Dimension(Connection(this, 0), Connection(this, 1.0), DTLinear, this);
+
+ if (parent)
+//{
+//printf("Line::SetDimensionOnLine(): Adding to parent...\n");
+ parent->Add(dimension);
+//}
+ }
+ else
+ {
+ dimension->Connect(this, 0);
+ dimension->Connect(this, 1.0);
+ }
+
+ // Make sure the Dimension is connected to us...
+ Connect(dimension, 0);
+ Connect(dimension, 1.0);
+}
+
+
+Object * Line::FindAttachedDimension(void)
+{
+ // Is there anything connected to this line? If not, return NULL
+ if (connected.size() < 2)
+ return NULL;
+
+ // Otherwise, we have to search our objects to see if there's a likely
+ // candidate. In this case, we're looking for a pointer to the same object
+ // with a parameter of 0 and 1 respectively. This is O((n^2)/2).
+ for(uint i=0; i<connected.size(); i++)
+ {
+ for(uint j=i+1; j<connected.size(); j++)
+ {
+//printf("Line: connected[i]=%X, connected[j]=%X, connected[i].t=%lf, connected[j].t=%lf\n", connected[i].object, connected[j].object, connected[i].t, connected[j].t);
+ if ((connected[i].object == connected[j].object)
+ && ((connected[i].t == 0 && connected[j].t == 1.0)
+ || (connected[i].t == 1.0 && connected[j].t == 0)))
+ return connected[i].object;
+ }
+ }
+
+ // Didn't find anything, so return NULL
+ return NULL;