]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Further progress on Polylines: Polylines can be selected and moved.
[architektonas] / src / drawingview.cpp
index 39196a753646a9eb7929e8d699b9e21f89c8fce3..e65bbe92de99f12d47f6f2e12596c25d33485c1d 100644 (file)
@@ -459,31 +459,18 @@ void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool
                {
                        painter->SetBrush(QBrush(Qt::NoBrush));
                        Polyline * pl = (Polyline *)obj;
-                       Point lastp;
-                       double lastbump;
 
-                       for(VPVectorIter i=pl->points.begin(); i!=pl->points.end(); i++)
+                       for(long unsigned int i=0; i<(pl->points.size()-1); i++)
                        {
-                               if (i != pl->points.begin())
-                               {
-                                       Point p = ((Object *)(*i))->p[0];
-                                       double bump = ((Object *)(*i))->length;
-
-                                       if (lastbump == 0)
-                                               painter->DrawLine(lastp, p);
-                                       else
-                                       {
-                                               Arc a = Geometry::Unpack(lastp, p, lastbump);
-                                               painter->DrawArc(a.p[0], a.radius[0], a.angle[0], a.angle[1]);
-                                       }
+                               Point p1 = pl->points[i];
+                               Point p2 = pl->points[i + 1];
 
-                                       lastp = p;
-                                       lastbump = bump;
-                               }
+                               if (p1.b == 0)
+                                       painter->DrawLine(p1, p2);
                                else
                                {
-                                       lastp = ((Object *)(*i))->p[0];
-                                       lastbump = ((Object *)(*i))->length;
+                                       Arc a = Geometry::Unpack(p1, p2, p1.b);
+                                       painter->DrawArc(a.p[0], a.radius[0], a.angle[0], a.angle[1]);
                                }
                        }
 
@@ -2397,6 +2384,7 @@ Point DrawingView::SnapPointToGrid(Point point)
        point.y = floor(point.y);
        point.z = 0;                                    // Make *sure* Z doesn't go anywhere!!!
        point *= Global::gridSpacing;
+
        return point;
 }
 
@@ -2441,68 +2429,14 @@ Rect DrawingView::GetObjectExtents(Object * obj)
        case OTArc:
        {
                Arc * a = (Arc *)obj;
+               rect = a->Bounds();
+               break;
+       }
 
-               double start = a->angle[0];
-               double end = start + a->angle[1];
-
-               // Swap 'em if the span is negative...
-               if (a->angle[1] < 0)
-               {
-                       end = a->angle[0];
-                       start = end + a->angle[1];
-               }
-
-               rect = Rect(Point(cos(start), sin(start)), Point(cos(end), sin(end)));
-
-               // If the end of the arc is before the beginning, add 360 degrees to it
-               if (end < start)
-                       end += TAU;
-
-/*
-Find which quadrant the start angle is in (consider the beginning of the 90° angle to be in the quadrant, the end to be in the next quadrant).  Then, divide the span into 90° segments.  The integer portion is the definite axis crossings; the remainder needs more scrutiny.  There will be an additional axis crossing if the the sum of the start angle and the remainder is > 90°.
-*/
-#if 1
-               int quadStart = (int)(a->angle[0] / QTR_TAU);
-               double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
-               int numAxes = (int)((a->angle[1] + qsRemain) / QTR_TAU);
-
-               double axis[4] = { 0, 0, 0, 0 };
-               axis[0] = rect.t, axis[1] = rect.l, axis[2] = rect.b, axis[3] = rect.r;
-               double box[4] = { 1.0, -1.0, -1.0, 1.0 };
-
-               for(int i=0; i<numAxes; i++)
-                       axis[(quadStart + i) % 4] = box[(quadStart + i) % 4];
-
-               // The rect is constructed the same way we traverse the axes: TLBR
-               Rect r2(axis[0], axis[1], axis[2], axis[3]);
-
-               rect |= r2;
-#else
-               // Adjust the bounds depending on which axes are crossed
-               if ((start < QTR_TAU) && (end > QTR_TAU))
-                       rect.t = 1.0;
-
-               if ((start < HALF_TAU) && (end > HALF_TAU))
-                       rect.l = -1.0;
-
-               if ((start < THREE_QTR_TAU) && (end > THREE_QTR_TAU))
-                       rect.b = -1.0;
-
-               if ((start < TAU) && (end > TAU))
-                       rect.r = 1.0;
-
-               if ((start < (TAU + QTR_TAU)) && (end > (TAU + QTR_TAU)))
-                       rect.t = 1.0;
-
-               if ((start < (TAU + HALF_TAU)) && (end > (TAU + HALF_TAU)))
-                       rect.l = -1.0;
-
-               if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
-                       rect.b = -1.0;
-#endif
-
-               rect *= a->radius[0];
-               rect.Translate(a->p[0]);
+       case OTPolyline:
+       {
+               Polyline * p = (Polyline *)obj;
+               rect = p->Bounds();
                break;
        }
 
@@ -2569,58 +2503,7 @@ void DrawingView::CheckObjectBounds(void)
                case OTArc:
                {
                        Arc * a = (Arc *)obj;
-
-                       double start = a->angle[0];
-                       double end = start + a->angle[1];
-
-                       // Swap 'em if the span is negative...
-                       if (a->angle[1] < 0)
-                       {
-                               end = a->angle[0];
-                               start = end + a->angle[1];
-                       }
-
-                       // If the end of the arc is before the beginning, add 360 degrees
-                       // to it
-                       if (end < start)
-                               end += TAU;
-
-#if 1
-                       int quadStart = (int)(a->angle[0] / QTR_TAU);
-                       double qsRemain = a->angle[0] - ((double)quadStart * QTR_TAU);
-                       int numAxes = (int)((a->angle[1] + qsRemain) / QTR_TAU);
-
-                       Rect bounds(sin(start), cos(start), sin(end), cos(end));
-                       const double box[4] = { 1.0, -1.0, -1.0, 1.0 };
-
-                       for(int i=0; i<numAxes; i++)
-                               bounds[(quadStart + i) % 4] = box[(quadStart + i) % 4];
-#else
-                       // Adjust the bounds depending on which axes are crossed
-                       if ((start < QTR_TAU) && (end > QTR_TAU))
-                               bounds.t = 1.0;
-
-                       if ((start < HALF_TAU) && (end > HALF_TAU))
-                               bounds.l = -1.0;
-
-                       if ((start < THREE_QTR_TAU) && (end > THREE_QTR_TAU))
-                               bounds.b = -1.0;
-
-                       if ((start < TAU) && (end > TAU))
-                               bounds.r = 1.0;
-
-                       if ((start < (TAU + QTR_TAU)) && (end > (TAU + QTR_TAU)))
-                               bounds.t = 1.0;
-
-                       if ((start < (TAU + HALF_TAU)) && (end > (TAU + HALF_TAU)))
-                               bounds.l = -1.0;
-
-                       if ((start < (TAU + THREE_QTR_TAU)) && (end > (TAU + THREE_QTR_TAU)))
-                               bounds.b = -1.0;
-#endif
-
-                       bounds *= a->radius[0];
-                       bounds.Translate(a->p[0]);
+                       Rect bounds = a->Bounds();
 
                        if (selection.Contains(bounds))
                                a->selected = true;
@@ -2631,15 +2514,9 @@ void DrawingView::CheckObjectBounds(void)
                case OTPolyline:
                {
                        Polyline * pl = (Polyline *)obj;
-                       Rect r(((Object *)(pl->points[0]))->p[0]);
+                       Rect bounds = pl->Bounds();
 
-                       for(int i=0; i<(pl->points.size()-1); i++)
-                       {
-                               r += ((Object *)(pl->points[i]))->p[0];
-                               r += ((Object *)(pl->points[i + 1]))->p[0];
-                       }
-
-                       if (selection.Contains(r))
+                       if (selection.Contains(bounds))
                                pl->selected = true;
 
                        break;
@@ -2745,7 +2622,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                else if ((distance * Global::zoom) < 5.0)
                        obj->hitObject = true;
 
-               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject ? true : false);
+               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject);
 
                if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHO != obj->hitObject))
                        needUpdate = true;
@@ -2768,7 +2645,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
                        obj->hitObject = true;
 
-               obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
+               obj->hovered = (obj->hitPoint[0] || obj->hitObject);
 
                if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
                        needUpdate = true;
@@ -2790,7 +2667,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                // Get the span that we're pointing at...
                double span = angle - obj->angle[0];
 
-               // N.B.: Still need to hit test the arc start & arc span handles...
+               // N.B.: Still need to hit test the arc start & arc span handles... [looks like it's DONE?]
                double spanAngle = obj->angle[0] + obj->angle[1];
                Point handle1 = obj->p[0] + (Vector(cos(obj->angle[0]), sin(obj->angle[0])) * obj->radius[0]);
                Point handle2 = obj->p[0] + (Vector(cos(spanAngle), sin(spanAngle)) * obj->radius[0]);
@@ -2818,7 +2695,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
                        obj->hitObject = true;
 
-               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject ? true : false);
+               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject);
 
                if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHO != obj->hitObject))
                        needUpdate = true;
@@ -2826,6 +2703,86 @@ bool DrawingView::HitTest(Object * obj, Point point)
                break;
        }
 
+       case OTPolyline:
+       {
+               Polyline * pl = (Polyline *)obj;
+               bool oldHP0 = pl->hitPoint[0], oldHO = pl->hitObject;
+               pl->hitPoint[0] = pl->hitObject = false;
+
+               for(long unsigned int i=0; i<(pl->points.size()-1); i++)
+               {
+                       Point p1 = pl->points[i];
+                       Point p2 = pl->points[i + 1];
+
+                       double dist1 = Vector::Magnitude(p1, point) * Global::zoom;
+                       double dist2 = Vector::Magnitude(p2, point) * Global::zoom;
+
+                       // Check for endpoints of lines and/or arcs first
+                       if (dist1 < 8.0)
+                       {
+                               pl->hitPoint[0] = true;
+                               hoverPoint = p1;
+                               hoverPointValid = true;
+                               pl->ptNum = i;
+                       }
+                       else if (dist2 < 8.0)
+                       {
+                               pl->hitPoint[0] = true;
+                               hoverPoint = p2;
+                               hoverPointValid = true;
+                               pl->ptNum = i + 1;
+                       }
+                       // Check for object (line/arc) last
+                       else if (p1.b == 0)
+                       {
+                               double t = Geometry::ParameterOfLineAndPoint(p1, p2, point);
+                               double objDist;
+
+                               // No bump == check for line proximity
+                               if (t < 0.0)
+                                       objDist = dist1;
+                               else if (t > 1.0)
+                                       objDist = dist2;
+                               else
+                               {
+                                       Line l(p1, p2);
+                                       Vector v1 = l.Vect();
+                                       Vector v2(p1, point);
+                                       objDist = fabs((v1.x * v2.y - v2.x * v1.y) / l.Length()) * Global::zoom;
+                               }
+
+                               if (objDist < 5.0)
+                                       pl->hitObject = true;
+                       }
+                       else
+                       {
+                               // We have a bump == check for arc proximity
+                               Arc a = Geometry::Unpack(p1, p2, p1.b);
+                               double length = Vector::Magnitude(a.p[0], point);
+                               double angle = Vector::Angle(a.p[0], point);
+                               double span = angle - a.angle[0];
+
+                               // Ensure point span is positive if we have a positive arc span
+                               if (span < 0 && a.angle[1] > 0)
+                                       span += TAU;
+
+                               // Ensure point span is negative if we have a negative arc span
+                               if (span > 0 && a.angle[1] < 0)
+                                       span -= TAU;
+
+                               if (((fabs(length - a.radius[0]) * Global::zoom) < 2.5) && (fabs(span) < fabs(a.angle[1])))
+                                       pl->hitObject = true;
+                       }
+               }
+
+               pl->hovered = (pl->hitPoint[0] || pl->hitObject);
+
+               if ((oldHP0 != pl->hitPoint[0]) || (oldHO != pl->hitObject))
+                       needUpdate = true;
+
+               break;
+       }
+
        case OTDimension:
        {
                bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHP3 = obj->hitPoint[3], oldHP4 = obj->hitPoint[4], oldHO = obj->hitObject;
@@ -2878,7 +2835,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                else if ((hCS2Point.Magnitude() * Global::zoom) < 8.0)
                        obj->hitPoint[4] = true;
 
-               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject ? true : false);
+               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject);
 
                if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHP3 != obj->hitPoint[3]) || (oldHP4 != obj->hitPoint[4]) || (oldHO != obj->hitObject))
                        needUpdate = true;
@@ -2898,7 +2855,7 @@ bool DrawingView::HitTest(Object * obj, Point point)
                if (r.Contains(point))
                        obj->hitObject = true;
 
-               obj->hovered = (obj->hitObject ? true : false);
+               obj->hovered = obj->hitObject;
 
                if (oldHO != obj->hitObject)
                        needUpdate = true;
@@ -3096,11 +3053,16 @@ N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not*
                        obj->p[0] = point;
                else if (obj->hitObject)
                {
-                       double oldRadius = obj->length;
-                       obj->radius[0] = Vector::Magnitude(obj->p[0], point);
+                       if (shiftDown)
+                       {
+                               double oldRadius = obj->length;
+                               obj->radius[0] = Vector::Magnitude(obj->p[0], point);
 
-                       QString text = QObject::tr("Radius: %1\nScale: %2%");
-                       informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
+                               QString text = QObject::tr("Radius: %1\nScale: %2%");
+                               informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
+                       }
+                       else
+                               obj->p[0] += delta;
                }
 
                break;
@@ -3169,16 +3131,34 @@ N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not*
                {
                        if (shiftDown)
                        {
-                               return;
+                               obj->radius[0] = Vector::Magnitude(obj->p[0], point);
+                               QString text = QObject::tr("Radius: %1");
+                               informativeText = text.arg(obj->radius[0], 0, 'f', 4);
                        }
-
-                       obj->radius[0] = Vector::Magnitude(obj->p[0], point);
-                       QString text = QObject::tr("Radius: %1");
-                       informativeText = text.arg(obj->radius[0], 0, 'f', 4);
+                       else
+                               obj->p[0] += delta;
                }
 
                break;
 
+       case OTPolyline:
+       {
+#if 1
+               // Do this for now...
+               ((Polyline *)obj)->Translate(delta);
+//             Polyline * pl = (Polyline *)obj;
+
+//             for(long unsigned int i=0; i<pl->points.size(); i++)
+//                     pl->points[i] += delta;
+#else
+               Polyline * pl = (Polyline *)obj;
+
+               for(long unsigned int i=0; i<(pl->points.size()-1); i++)
+#endif
+
+               break;
+       }
+
        case OTDimension:
                if (obj->hitPoint[0])
                        obj->p[0] = point;