]> Shamusworld >> Repos - architektonas/blobdiff - src/line.cpp
Fixed Arc to give continuous feedback like Line and Circle do.
[architektonas] / src / line.cpp
index aa5054bab3da9ea9bb79ca65b8cf695093ccb687..e80e988797c28004cd84d45c7ba76411bbad1049 100644 (file)
@@ -75,29 +75,22 @@ Line::~Line()
                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(point1, v2);
 
                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->DrawLine(v2, point2);
                }
        }
-// Problem: when drawing at large zoom levels, this throws away precision thus
-//          causing the line to rendered too short. !!! FIX !!! [DONE]
        else
-//             painter->DrawLine((int)position.x, (int)position.y, (int)endpoint.x, (int)endpoint.y);
                painter->DrawLine(position, endpoint);
 
-       // If we're rotating or setting the span, draw an information panel
-       // showing both absolute and relative angles being set.
+       // If we're dragging an endpoint, draw an information panel showing both
+       // the length and angle being set.
        if (draggingHandle1 || draggingHandle2)
        {
                double absAngle = (Vector(endpoint - position).Angle()) * RADIANS_TO_DEGREES;
-//             double relAngle = (startAngle >= oldAngle ? startAngle - oldAngle :
-//                     startAngle - oldAngle + (2.0 * PI)) * RADIANS_TO_DEGREES;
                double absLength = Vector(position - endpoint).Magnitude();
 
                QString text;
@@ -108,16 +101,14 @@ Line::~Line()
                QPen pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine);
                painter->SetPen(pen);
                painter->SetBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F)));
-               QRectF textRect(10.0, 10.0, 270.0, 70.0);       // x, y, w, h
+               QRectF textRect(10.0, 10.0, 270.0, 70.0);       // x, y, w, h (in Qt coords)
                painter->DrawRoundedRect(textRect, 7.0, 7.0);
 
                textRect.setLeft(textRect.left() + 14);
                painter->SetFont(*Object::font);
-//                     pen = QPen(QColor(0xDF, 0x5F, 0x00), 1.0, Qt::SolidLine);
                pen = QPen(QColor(0x00, 0x5F, 0xDF));
                painter->SetPen(pen);
                painter->DrawText(textRect, Qt::AlignVCenter, text);
-//             painter->SetPen(QPen(QColor(0xDF, 0x5F, 0x00)));
        }
 }
 
@@ -132,8 +123,11 @@ Line::~Line()
 {
        // We can assume this, since this is a mouse down event here.
        objectWasDragged = false;
+//     SaveHitState();
        HitTest(point);
+//     return HitStateChanged();
 
+// this is shite. this should be checked for in the Container, not here!
        // If we're part of a non-top-level container, send this signal to it
        if (parent->type == OTContainer && !((Container *)parent)->isTopLevelContainer
                && (hitLine || hitPoint1 || hitPoint2))
@@ -300,8 +294,10 @@ Like so:
 #if 0
                if (selection.normalized().contains(Extents()))
 #else
-               if (selection.normalized().contains(position.x, position.y)
-                       && selection.normalized().contains(endpoint.x, endpoint.y))
+//             if (selection.normalized().contains(position.x, position.y)
+//                     && selection.normalized().contains(endpoint.x, endpoint.y))
+               if (selection.contains(position.x, position.y)
+                       && selection.contains(endpoint.x, endpoint.y))
 #endif
                        state = OSSelected;
                else
@@ -310,9 +306,11 @@ Like so:
                return;
        }
 
-       // Hit test tells us what we hit (if anything) through boolean variables. It
-       // also tells us whether or not the state changed.
-       needUpdate = HitTest(point);
+       // Hit test tells us what we hit (if anything) through boolean variables. (It
+       // also tells us whether or not the state changed. --not any more)
+       SaveHitState();
+       HitTest(point);
+       needUpdate = HitStateChanged();
 
        objectWasDragged = (draggingLine | draggingHandle1 | draggingHandle2);
 
@@ -363,16 +361,6 @@ try to do the right thing, most of the time. :-)
                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.
@@ -424,22 +412,21 @@ the horizontal line or vertical line that intersects from the current mouse posi
                        }
                        else                                    // endpoint
                        {
-//                             Vector v1 = endpoint - position;
                                Vector v = Vector(endpoint - position).Unit() * length;
                                endpoint = position + v;
                        }
                }
                else
                {
-                       // Otherwise, we calculate the new length, just in case on the next move
-                       // it turns out to have a fixed length. :-)
+                       // Otherwise, we calculate the new length, just in case on the next
+                       // move 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. :-)
+                       // Calculate the new angle, just in case on the next move it turns
+                       // out to be fixed. :-)
                        angle = Vector(endpoint - position).Unit();
                }
        }
@@ -448,14 +435,6 @@ the horizontal line or vertical line that intersects from the current mouse posi
        draggingHandle1 = false;
        draggingHandle2 = false;
 
-//     hitPoint1 = hitPoint2 = hitLine = false;
-
-       // Here we check for just a click: If object was clicked and dragged, then
-       // revert to the old state (OSInactive). Otherwise, keep the new state that
-       // we set.
-/*Maybe it would be better to just check for "object was dragged" state and not have to worry
-about keeping track of old states...
-*/
        if (objectWasDragged)
                state = oldState;
 }
@@ -463,28 +442,23 @@ about keeping track of old states...
 
 /*virtual*/ bool Line::HitTest(Point point)
 {
-       SaveState();
+//     SaveHitState();
 
        hitPoint1 = hitPoint2 = hitLine = false;
        Vector lineSegment = endpoint - position;
        Vector v1 = point - position;
        Vector v2 = point - endpoint;
-       double parameterizedPoint = lineSegment.Dot(v1) / lineSegment.Magnitude(), distance;
+       double t = Vector::Parameter(position, endpoint, point);
+       double distance;
 
        // Geometric interpretation:
-       // The parameterized point on the vector lineSegment is where the perpendicular
-       // intersects lineSegment. If pp < 0, then the perpendicular lies beyond the 1st
-       // endpoint. If pp > length of ls, then the perpendicular lies beyond the 2nd endpoint.
-
-       if (parameterizedPoint < 0.0)
-               distance = v1.Magnitude();
-       else if (parameterizedPoint > lineSegment.Magnitude())
-               distance = v2.Magnitude();
-       else
-               // distance = ?Det?(ls, v1) / |ls|
-               distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y) / lineSegment.Magnitude());
+       // 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 the above:
+       // 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.
@@ -502,9 +476,15 @@ about keeping track of old states...
        // all other rows, we end up with the matrix on the right which greatly
        // simplifies the calculation of the determinant.
 
-//How do we determine distance here? Especially if zoomed in or out???
-//#warning "!!! Distances tested for may not be valid if zoomed in or out !!!"
-// [FIXED]
+       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)
@@ -512,7 +492,8 @@ about keeping track of old states...
        else if ((distance * Painter::zoom) < 5.0)
                hitLine = true;
 
-       return StateChanged();
+       return (hitPoint1 || hitPoint2 || hitLine ? true : false);
+//     return HitStateChanged();
 }
 
 
@@ -539,12 +520,13 @@ about keeping track of old states...
 {
 #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.
+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.
+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);
 }
@@ -579,6 +561,23 @@ you then *definitely* do not want them to have the same reference number.
 }
 
 
+/*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)
+{
+}
+
+
 void Line::SetDimensionOnLine(Dimension * dimension/*=NULL*/)
 {
        // If they don't pass one in, create it for the caller.
@@ -632,7 +631,7 @@ Object * Line::FindAttachedDimension(void)
 }
 
 
-void Line::SaveState(void)
+void Line::SaveHitState(void)
 {
        oldHitPoint1 = hitPoint1;
        oldHitPoint2 = hitPoint2;
@@ -640,7 +639,7 @@ void Line::SaveState(void)
 }
 
 
-bool Line::StateChanged(void)
+bool Line::HitStateChanged(void)
 {
        if ((hitPoint1 != oldHitPoint1) || (hitPoint2 != oldHitPoint2) || (hitLine != oldHitLine))
                return true;