+
+ // The parameter is a percentage of the length of the vector, so all we
+ // have to do is scale the vector by it to find the point.
+ return position + (Vector(position, endpoint) * parameter);
+}
+
+
+/*virtual*/ void Line::MovePointAtParameter(double parameter, Vector v)
+{
+ if (parameter == 0)
+ position += v;
+ else if (parameter == 1.0)
+ endpoint += v;
+ else
+ {} // Not sure how to handle this case :-P
+}
+
+
+/*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(Point point, double angle)
+{
+ Point l1 = Geometry::RotatePointAroundPoint(position, point, angle);
+ Point l2 = Geometry::RotatePointAroundPoint(endpoint, point, angle);
+ position = l1;
+ endpoint = l2;
+}
+
+
+/*virtual*/ void Line::Scale(Point point, double amount)
+{
+}
+
+
+/*virtual*/ void Line::Mirror(Point p1, Point p2)
+{
+ Point l1 = Geometry::MirrorPointAroundLine(position, p1, p2);
+ Point l2 = Geometry::MirrorPointAroundLine(endpoint, p1, p2);
+ position = l1;
+ endpoint = l2;
+}
+
+
+/*virtual*/ void Line::Save(void)
+{
+ Object::Save();
+ oldEndpoint = endpoint;
+}
+
+
+/*virtual*/ void Line::Restore(void)
+{
+ Object::Restore();
+ endpoint = oldEndpoint;
+}
+
+
+void Line::SetDimensionOnLine(Dimension * dimension/*= NULL*/)
+{
+ // If they don't pass one in, create it for the caller.
+ // But ONLY if this line has a parent container!
+ // This is really bad to do here, it should be done in the parent container, always!
+#warning "!!! Parent container should be creating Dimension object !!!"
+ if ((dimension == NULL) && (parent != NULL))
+ {
+//printf("Line::SetDimensionOnLine(): Creating new dimension...\n");
+ dimension = new Dimension(position, endpoint, DTLinear, parent);
+// dimension = new Dimension(Connection(this, 0), Connection(this, 1.0), DTLinear, this);
+
+ // THIS IS SERIOUS!!! WITHOUT A PARENT, THIS OBJECT IS IN LIMBO!!!
+// if (parent)
+//{
+//printf("Line::SetDimensionOnLine(): Adding to parent...\n");
+ parent->Add(dimension);
+//}
+ }
+
+ dimension->Connect(this, 0);
+ dimension->Connect(this, 1.0);
+
+ // Make sure the Dimension is connected to us...
+ Connect(dimension, 0);
+ Connect(dimension, 1.0);
+
+ dimension->position = position;
+ dimension->endpoint = endpoint;
+}
+
+
+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;
+}
+
+
+void Line::SaveHitState(void)
+{
+ oldHitPoint1 = hitPoint1;
+ oldHitPoint2 = hitPoint2;
+ oldHitLine = hitLine;
+}
+
+
+bool Line::HitStateChanged(void)
+{
+ if ((hitPoint1 != oldHitPoint1) || (hitPoint2 != oldHitPoint2) || (hitLine != oldHitLine))
+ return true;
+
+ return false;
+}
+
+
+/*
+Intersection of two lines:
+
+Find where the lines with equations r = i + j + t (3i - j) and r = -i + s (j) intersect.
+
+When they intersect, we can set the equations equal to one another:
+
+i + j + t (3i - j) = -i + s (j)
+
+Equating coefficients:
+1 + 3t = -1 and 1 - t = s
+So t = -2/3 and s = 5/3
+
+The position vector of the intersection point is therefore given by putting t = -2/3 or s = 5/3 into one of the above equations. This gives -i +5j/3 .
+
+
+so, let's say we have two lines, l1 and l2. Points are v0(p0x, p0y), v1(p1x, p1y) for l1
+and v2(p2x, p2y), v3(p3x, p3y) for l2.
+
+d1 = v1 - v0, d2 = v3 - v2
+
+Our parametric equations for the line then are:
+
+r1 = v0 + t(d1)
+r2 = v2 + s(d2)
+
+Set r1 = r2, thus we have:
+
+v0 + t(d1) = v2 + s(d2)
+
+Taking coefficients, we have:
+
+p0x + t(d1x) = p2x + s(d2x)
+p0y + t(d1y) = p2y + s(d2y)
+
+rearranging we get:
+
+t(d1x) - s(d2x) = p2x - p0x
+t(d1y) - s(d2y) = p2y - p0y
+
+Determinant D is ad - bc where the matrix looks like:
+
+a b
+c d
+
+so D = (d1x)(d2y) - (d2x)(d1y)
+if D = 0, the lines are parallel.
+Dx = (p2x - p0x)(d2y) - (d2x)(p2y - p0y)
+Dy = (d1x)(p2y - p0y) - (p2x - p0x)(d1y)
+t = Dx/D, s = Dy/D
+
+We only need to calculate t, as we can then multiply it by d1 to get the intersection point.
+
+---------------------------------------------------------------------------------------------------
+
+The first and most preferred method for intersection calculation is the perp-product calculation. There are two vectors, v1 and v2. Create a third vector vector between the starting points of these vectors, and calculate the perp product of v2 and the two other vectors. These two scalars have to be divided to get the mulitplication ratio of v1 to reach intersection point. So:
+
+v1 ( bx1 , by1 );
+v2 ( bx2 , by2 );
+v3 ( bx3 , by3 );
+
+Perp product is equal with dot product of normal of first vector and the second vector, so we need normals:
+
+n1 ( -by1 , bx1 );
+n3 ( -by3 , bx3 );
+
+Dot products:
+
+dp1 = n3 . v2 = -by3 * bx2 + bx3 * by2;
+dp2 = n1 . v2 = -by1 * bx2 + bx1 * by2;
+
+ratio = dp1 / dp2;
+crossing vector = v1 * ratio;
+
+And that's it.
+
+-----------------------------------
+
+So... to code this, let's say we have two Lines: l1 & l2.
+
+Vector v1 = l1.endpoint - l1.position;
+Vector v2 = l2.endpoint - l2.position;
+Vector v3 = v2 - v1;
+
+Vector normal1(-v1.y, v1.x);
+Vector normal3(-v3.y, v3.x);
+
+double dotProduct1 = v2.Dot(normal1);
+double dotProduct2 = v2.Dot(normal3);
+
+if (dotProduct2 == 0)
+ return ParallelLines;
+else
+{
+ // I think we'd still have to add the intersection to the position point to get the intersection...
+ Point intersection = v1 * (dotProduct1 / dotProduct2);
+ return intersection;
+}
+*/
+