// "Fixed Length" button is down
// JLH 04/27/2011 Fixed attached dimension to stay a correct length when
// "Fixed Length" button is *not* down ;-)
-// JLH 05/29/2011 Added mouseover hints
+// JLH 05/29/2011 Added (some) mouseover hints
//
#include "line.h"
#include <QtGui>
#include "dimension.h"
+#include "painter.h"
+
Line::Line(Vector p1, Vector p2, Object * p/*= NULL*/): Object(p1, p), endpoint(p2),
draggingLine(false), draggingHandle1(false), draggingHandle2(false), //needUpdate(false),
- length(Vector::Magnitude(p2, p1)), hitPoint1(false), hitPoint2(false), hitLine(false)
+ length(Vector::Magnitude(p2, p1)), angle(Vector(endpoint - position).Unit()),
+ hitPoint1(false), hitPoint2(false), hitLine(false)
{
}
Line::~Line()
{
+ // If there are any attached Dimensions, we must set the attachment points
+ // to NULL since they will no longer be valid.
+ if (attachedDimension)
+ {
+ attachedDimension->SetPoint1(NULL);
+ attachedDimension->SetPoint2(NULL);
+ }
+ // IT WOULD BE NICE to have any object points attached to this line automagically
+ // connect to this dimension object at this point, instead of just becoming
+ // detached.
}
-/*virtual*/ void Line::Draw(QPainter * painter)
+/*virtual*/ void Line::Draw(Painter * painter)
{
- painter->setPen(QPen(Qt::red, 2.0, Qt::DotLine));
+ painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
if ((state == OSSelected) || ((state == OSInactive) && hitPoint1))
- painter->drawEllipse(QPointF(position.x, position.y), 4.0, 4.0);
+ painter->DrawHandle(position);
if ((state == OSSelected) || ((state == OSInactive) && hitPoint2))
- painter->drawEllipse(QPointF(endpoint.x, endpoint.y), 4.0, 4.0);
+ painter->DrawHandle(endpoint);
if ((state == OSInactive) && !hitLine)
- painter->setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+ painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
if (Object::fixedLength && (draggingHandle1 || draggingHandle2))
{
Vector current(point2 - point1);
Vector v = current.Unit() * length;
Vector v2 = point1 + v;
- painter->drawLine((int)point1.x, (int)point1.y, (int)v2.x, (int)v2.y);
+ painter->DrawLine((int)point1.x, (int)point1.y, (int)v2.x, (int)v2.y);
if (current.Magnitude() > length)
{
- painter->setPen(QPen(QColor(128, 0, 0), 1.0, Qt::DashLine));
- painter->drawLine((int)v2.x, (int)v2.y, (int)point2.x, (int)point2.y);
+ painter->SetPen(QPen(QColor(128, 0, 0), 1.0, Qt::DashLine));
+ painter->DrawLine((int)v2.x, (int)v2.y, (int)point2.x, (int)point2.y);
}
}
else
- painter->drawLine((int)position.x, (int)position.y, (int)endpoint.x, (int)endpoint.y);
+ painter->DrawLine((int)position.x, (int)position.y, (int)endpoint.x, (int)endpoint.y);
}
/*virtual*/ Vector Line::Center(void)
/*virtual*/ bool Line::Collided(Vector point)
{
-// Can't assume this!
-// Actually, we can, since this is a mouse down event here.
+ // We can assume this, since this is a mouse down event here.
objectWasDragged = false;
HitTest(point);
to only one point while at the same time you can have a dimension sitting on this line.
Since there's only *one* dimPoint for each point, this can be problematic...
+We solve this by allowing only *one* Dimension object to be attached to the Line,
+Arc, etc. and by giving the Dimension object a pointer to our endpoints.
+
+Problem still arises when we delete this object; The attached Dimension object will
+then have bad pointers! What it *should* do is delete the object if and only if this
+line is not attached to any other object. If it is, then one of those attachment
+points should be sent to the dimension object (done for position & endpoint).
+
+NOTE: The STL vector<T> *does not* take ownership of pointers, therefore is suitable
+ for our purposes
+
Also: It would be nice to have a preview of the dimension being drawn, with a modifier
key to make it draw/show on the other side...
Vector point1 = (draggingHandle1 ? endpoint : position);
Vector point2 = (draggingHandle1 ? position : endpoint);
+#if 0
Vector current(point2, point1);
Vector v = current.Unit() * length;
Vector v2 = point1 + v;
//bleh
if (!Object::fixedLength)
v2 = point2;
+#endif
+
+ if (Object::fixedAngle)
+ {
+ // Here we calculate the component of the current vector along the fixed angle.
+ // A_compB = (A . Bu) * Bu
+ double magnitudeAlongB = Vector::Dot(Vector(point2 - point1), angle);
+/*
+Actually, this isn't quite right. What we want to do is look for the intersection along either
+the horizontal line or vertical line that intersects from the current mouse position.
+*/
+
+ if (draggingHandle1)
+ position = endpoint + (angle * magnitudeAlongB);
+
+ if (draggingHandle2)
+ endpoint = position + (angle * magnitudeAlongB);
+ }
+// else
+// v2 = point2;
//If we tell the dimension to flip sides, this is no longer a valid
//assumption. !!! FIX !!!
// it turns out to have a fixed length. :-)
length = Vector(endpoint - position).Magnitude();
}
+
+ if (!Object::fixedAngle)
+ {
+ // Calculate the new angle, just in case on the next move it turns out to
+ // be fixed. :-)
+ angle = Vector(endpoint - position).Unit();
+ }
}
draggingLine = false;