]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Added preliminary circle-to-circle intersection code.
[architektonas] / src / drawingview.cpp
index 7b493234ce2550531f7986e744d2115b599cf042..5ae9c9a9081e5ccf121c82958eac22e6634d6400 100644 (file)
@@ -20,6 +20,7 @@
 // STILL TO BE DONE:
 //
 // - Lots of stuff
+// - Layer locking (hiding works)
 //
 
 // Uncomment this for debugging...
@@ -49,8 +50,8 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        useAntialiasing(true), numSelected(0), numHovered(0), shiftDown(false),
        ctrlDown(false),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
-       scale(1.0), offsetX(-10), offsetY(-10),// document(Vector(0, 0)),
-       gridPixels(0), collided(false)//, toolAction(NULL)
+       scale(1.0), offsetX(-10), offsetY(-10),
+       gridPixels(0), collided(false), hoveringIntersection(false)
 {
 //     document.isTopLevelContainer = true;
 //wtf? doesn't work except in c++11??? document = { 0 };
@@ -84,6 +85,7 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        line->thickness = 2.0;
        line->style = LSDash;
        line->color = 0xFF7F00;
+       line->layer = 0;
        document.objects.push_back(line);
        document.objects.push_back(new Line(Vector(50, 40), Vector(10, 83)));
        document.objects.push_back(new Line(Vector(10, 83), Vector(17, 2)));
@@ -265,13 +267,77 @@ zero; so we do another modulus operation on the result to achieve this.
 }
 
 
-void DrawingView::SetCurrentLayer(int layer)
+void DrawingView::SetCurrentLayer(int /*layer*/)
 {
-       Global::currentLayer = layer;
+//Not needed anymore...
+//     Global::currentLayer = layer;
 //printf("DrawingView::CurrentLayer = %i\n", layer);
 }
 
 
+//
+// Basically, we just make a single pass through the Container. If the layer #
+// is less than the layer # being deleted, then do nothing. If the layer # is
+// equal to the layer # being deleted, then delete the object. If the layer #
+// is greater than the layer # being deleted, then set the layer # to its layer
+// # - 1.
+//
+void DrawingView::DeleteCurrentLayer(int layer)
+{
+//printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer);
+       std::vector<void *>::iterator i = document.objects.begin();
+
+       while (i != document.objects.end())
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->layer < layer)
+                       i++;
+               else if (obj->layer == layer)
+               {
+                       document.objects.erase(i);
+                       delete obj;
+               }
+               else
+               {
+                       obj->layer--;
+                       i++;
+               }
+       }
+
+       // We've just done a destructive action, so update the screen!
+       update();
+}
+
+
+void DrawingView::HandleLayerToggle(void)
+{
+       // A layer's visibility was toggled, so update the screen...
+       update();
+}
+
+
+//
+// A layer was moved up or down in the layer list, so we have to swap the
+// document's object's layer numbers in the layers that were swapped.
+//
+void DrawingView::HandleLayerSwap(int layer1, int layer2)
+{
+//printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
+       std::vector<void *>::iterator i;
+
+       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->layer == layer1)
+                       obj->layer = layer2;
+               else if (obj->layer == layer2)
+                       obj->layer = layer1;
+       }
+}
+
+
 QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event)
 {
        // This is undoing the transform, e.g. going from client coords to local coords.
@@ -306,7 +372,11 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
        painter.DrawLine(-16384, 0, 16384, 0);
 
        // Do object rendering...
-       RenderObjects(&painter, document.objects);
+       for(int i=0; i<Global::numLayers; i++)
+       {
+               if (Global::layerHidden[i] == false)
+                       RenderObjects(&painter, document.objects, i);
+       }
 
        // Do tool rendering, if any...
        if (Global::tool)
@@ -324,6 +394,9 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
                painter.DrawRect(Global::selection);
        }
 
+       if (hoveringIntersection)
+               painter.DrawHandle(intersectionPoint);
+
        if (!informativeText.isEmpty())
                painter.DrawInformativeText(informativeText);
 }
@@ -332,7 +405,7 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
 //
 // Renders objects in the passed in vector
 //
-void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
+void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int layer)
 {
        std::vector<void *>::iterator i;
 
@@ -341,6 +414,10 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
                Object * obj = (Object *)(*i);
                float scaledThickness = Global::scale * obj->thickness;
 
+               // If the object isn't on the current layer being drawn, skip it
+               if (obj->layer != layer)
+                       continue;
+
                if ((Global::tool == TTRotate) && ctrlDown && obj->selected)
                {
                        painter->SetPen(0x00FF00, 2.0, LSSolid);
@@ -585,6 +662,8 @@ void DrawingView::ToolHandler(int mode, Point p)
                ArcHandler(mode, p);
        else if (Global::tool == TTRotate)
                RotateHandler(mode, p);
+       else if (Global::tool == TTMirror)
+               MirrorHandler(mode, p);
 }
 
 
@@ -687,7 +766,7 @@ void DrawingView::ToolDraw(Painter * painter)
                {
                        if (toolPoint[0] == toolPoint[1])
                                return;
-                       
+
                        painter->DrawLine(toolPoint[0], toolPoint[1]);
                        // Likely we need a tool container for this... (now we do!)
 #if 0
@@ -702,14 +781,49 @@ void DrawingView::ToolDraw(Painter * painter)
 #endif
 
                        double absAngle = (Vector(toolPoint[1] - toolPoint[0]).Angle()) * RADIANS_TO_DEGREES;
-
                        QString text = QChar(0x2221) + QObject::tr(": %1");
                        informativeText = text.arg(absAngle);
 
                        if (ctrlDown)
                                informativeText += " (Copy)";
+               }
+       }
+       else if (Global::tool == TTMirror)
+       {
+               if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
+                       painter->DrawHandle(toolPoint[0]);
+               else if ((Global::toolState == TSPoint2) && shiftDown)
+                       painter->DrawHandle(toolPoint[1]);
+               else
+               {
+                       if (toolPoint[0] == toolPoint[1])
+                               return;
+                       
+                       Point mirrorPoint = toolPoint[0] + Vector(toolPoint[1], toolPoint[0]);
+//                     painter->DrawLine(toolPoint[0], toolPoint[1]);
+                       painter->DrawLine(mirrorPoint, toolPoint[1]);
+                       // Likely we need a tool container for this... (now we do!)
+#if 0
+                       if (ctrlDown)
+                       {
+                               painter->SetPen(0x00FF00, 2.0, LSSolid);
+                               overrideColor = true;
+                       }
+
+                       RenderObjects(painter, toolObjects);
+                       overrideColor = false;
+#endif
+
+                       double absAngle = (Vector(toolPoint[1] - toolPoint[0]).Angle()) * RADIANS_TO_DEGREES;
+
+                       if (absAngle > 180.0)
+                               absAngle -= 180.0;
 
-//                     painter->DrawInformativeText(text);
+                       QString text = QChar(0x2221) + QObject::tr(": %1");
+                       informativeText = text.arg(absAngle);
+
+                       if (ctrlDown)
+                               informativeText += " (Copy)";
                }
        }
 }
@@ -749,6 +863,7 @@ void DrawingView::LineHandler(int mode, Point p)
                else
                {
                        Line * l = new Line(toolPoint[0], toolPoint[1]);
+                       l->layer = Global::activeLayer;
                        document.objects.push_back(l);
                        toolPoint[0] = toolPoint[1];
                }
@@ -791,6 +906,7 @@ void DrawingView::CircleHandler(int mode, Point p)
                {
                        double length = Vector::Magnitude(toolPoint[0], toolPoint[1]);
                        Circle * c = new Circle(toolPoint[0], length);
+                       c->layer = Global::activeLayer;
                        document.objects.push_back(c);
                        toolPoint[0] = toolPoint[1];
                        Global::toolState = TSNone;
@@ -861,6 +977,7 @@ void DrawingView::ArcHandler(int mode, Point p)
                                span += PI_TIMES_2;
 
                        Arc * arc = new Arc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span);
+                       arc->layer = Global::activeLayer;
                        document.objects.push_back(arc);
                        Global::toolState = TSNone;
                }
@@ -970,6 +1087,109 @@ void DrawingView::RotateHandler(int mode, Point p)
 }
 
 
+void DrawingView::MirrorHandler(int mode, Point p)
+{
+       switch (mode)
+       {
+       case ToolMouseDown:
+               if (Global::toolState == TSNone)
+               {
+                       toolPoint[0] = p;
+                       SavePointsFrom(select, toolScratch);
+                       Global::toolState = TSPoint1;
+               }
+               else if (Global::toolState == TSPoint1)
+                       toolPoint[0] = p;
+               else
+                       toolPoint[1] = p;
+
+               break;
+       case ToolMouseMove:
+               if ((Global::toolState == TSPoint1) || (Global::toolState == TSNone))
+                       toolPoint[0] = p;
+               else if (Global::toolState == TSPoint2)
+               {
+                       toolPoint[1] = p;
+
+                       if (shiftDown)
+                               return;
+
+                       double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
+                       std::vector<void *>::iterator j = select.begin();
+                       std::vector<Object>::iterator i = toolScratch.begin();
+
+                       for(; i!=toolScratch.end(); i++, j++)
+                       {
+                               Object obj = *i;
+                               Point p1 = Geometry::MirrorPointAroundLine(obj.p[0], toolPoint[0], toolPoint[1]);
+                               Point p2 = Geometry::MirrorPointAroundLine(obj.p[1], toolPoint[0], toolPoint[1]);
+                               Object * obj2 = (Object *)(*j);
+                               obj2->p[0] = p1;
+                               obj2->p[1] = p2;
+
+                               if (obj.type == OTArc)
+                               {
+                                       // This is 2*mirror angle - obj angle - obj span
+                                       obj2->angle[0] = (2.0 * angle) - obj.angle[0] - obj.angle[1];
+
+                                       if (obj2->angle[0] > PI_TIMES_2)
+                                               obj2->angle[0] -= PI_TIMES_2;
+                               }
+                       }
+               }
+
+               break;
+       case ToolMouseUp:
+               if (Global::toolState == TSPoint1)
+               {
+                       Global::toolState = TSPoint2;
+                       // Prevent spurious line from drawing...
+                       toolPoint[1] = toolPoint[0];
+               }
+               else if ((Global::toolState == TSPoint2) && shiftDown)
+               {
+                       // Key override is telling us to make a new line, not continue the
+                       // previous one.
+                       toolPoint[0] = toolPoint[1];
+               }
+               else
+               {
+                       // Either we're finished with our rotate, or we're stamping a copy.
+                       if (ctrlDown)
+                       {
+                               // Stamp a copy of the selection at the current rotation & bail
+                               std::vector<void *> temp;
+                               CopyObjects(select, temp);
+                               ClearSelected(temp);
+                               AddObjectsTo(document.objects, temp);
+                               RestorePointsTo(select, toolScratch);
+                               return;
+                       }
+
+                       toolPoint[0] = p;
+                       Global::toolState = TSPoint1;
+                       SavePointsFrom(select, toolScratch);
+               }
+
+               break;
+       case ToolKeyDown:
+               // Reset the selection if shift held down...
+               if (shiftDown)
+                       RestorePointsTo(select, toolScratch);
+
+               break;
+       case ToolKeyUp:
+               // Reset selection when key is let up
+               if (!shiftDown)
+                       MirrorHandler(ToolMouseMove, toolPoint[1]);
+
+               break;
+       case ToolCleanup:
+               RestorePointsTo(select, toolScratch);
+       }
+}
+
+
 void DrawingView::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::LeftButton)
@@ -1034,6 +1254,7 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
        Global::selection.setBottomRight(QPointF(point.x, point.y));
        // Only needs to be done here, as mouse down is always preceded by movement
        Global::snapPointIsValid = false;
+       hoveringIntersection = false;
 
        // Scrolling...
        if (event->buttons() & Qt::MiddleButton)
@@ -1076,6 +1297,42 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
        // Do object hit testing...
        bool needUpdate = HitTestObjects(point);
 
+       // Check for multi-hover...
+       if (numHovered > 1)
+       {
+               GetHovered(hover);
+
+//             double t, u;
+//             int numIntersecting = Geometry::Intersects((Object *)hover[0], (Object *)hover[1], &t, &u);
+               Geometry::Intersects((Object *)hover[0], (Object *)hover[1]);
+               int numIntersecting = Global::numIntersectParams;
+               double t = Global::intersectParam[0];
+               double u = Global::intersectParam[1];
+
+               if (numIntersecting > 0)
+               {
+                       Vector v1 = Geometry::GetPointForParameter((Object *)hover[0], t);
+                       Vector v2 = Geometry::GetPointForParameter((Object *)hover[1], u);
+                       QString text = tr("Intersection t=%1 (%3, %4), u=%2 (%5, %6)");
+                       informativeText = text.arg(t).arg(u).arg(v1.x).arg(v1.y).arg(v2.x).arg(v2.y);
+
+                       hoveringIntersection = true;
+                       intersectionPoint = v1;
+               }
+
+               numIntersecting = Global::numIntersectPoints;
+
+               if (numIntersecting > 0)
+               {
+                       Vector v1 = Global::intersectPoint[0];
+                       QString text = tr("Intersection <%1, %2>");
+                       informativeText = text.arg(v1.x).arg(v1.y);
+
+                       hoveringIntersection = true;
+                       intersectionPoint = v1;
+               }
+       }
+
        // Do tool handling, if any are active...
        if (Global::tool)
        {