]> Shamusworld >> Repos - architektonas/commitdiff
Add ability to add Arcs to document.
authorShamus Hammons <jlhamm@acm.org>
Mon, 11 May 2015 12:46:28 +0000 (07:46 -0500)
committerShamus Hammons <jlhamm@acm.org>
Mon, 11 May 2015 12:46:28 +0000 (07:46 -0500)
src/drawingview.cpp
src/drawingview.h
src/structs.h
src/vector.cpp
src/vector.h

index 16280d6e9802e1d5132d931164e908d76b6a517a..9e1b56c784e02698733c85cd205c1bc913db372f 100644 (file)
@@ -571,6 +571,8 @@ void DrawingView::ToolHandler(int mode, Point p)
                LineHandler(mode, p);
        else if (Global::tool == TTCircle)
                CircleHandler(mode, p);
+       else if (Global::tool == TTArc)
+               ArcHandler(mode, p);
        else if (Global::tool == TTRotate)
                RotateHandler(mode, p);
 }
@@ -621,6 +623,50 @@ void DrawingView::ToolDraw(Painter * painter)
                        informativeText = text.arg(length);//.arg(absAngle);
                }
        }
+       else if (Global::tool == TTArc)
+       {
+               if (Global::toolState == TSNone)
+               {
+                       painter->DrawHandle(toolPoint[0]);
+               }
+               else if (Global::toolState == TSPoint2)
+               {
+                       double length = Vector::Magnitude(toolPoint[0], toolPoint[1]);
+                       painter->SetBrush(QBrush(Qt::NoBrush));
+                       painter->DrawEllipse(toolPoint[0], length, length);
+                       painter->DrawLine(toolPoint[0], toolPoint[1]);
+                       painter->DrawHandle(toolPoint[1]);
+                       QString text = tr("Radius: %1 in.");
+                       informativeText = text.arg(length);
+               }
+               else if (Global::toolState == TSPoint3)
+               {
+                       double angle = Vector::Angle(toolPoint[0], toolPoint[2]);
+                       painter->DrawLine(toolPoint[0], toolPoint[2]);
+                       painter->SetBrush(QBrush(Qt::NoBrush));
+                       painter->DrawEllipse(toolPoint[0], toolPoint[1].x, toolPoint[1].x);
+                       painter->DrawHandle(toolPoint[0] + (Vector(cos(angle), sin(angle)) * toolPoint[1].x));
+                       QString text = tr("Angle start: %1") + QChar(0x00B0);
+                       informativeText = text.arg(RADIANS_TO_DEGREES * angle);
+               }
+               else
+               {
+                       double angle = Vector::Angle(toolPoint[0], toolPoint[3]);
+                       double span = angle - toolPoint[2].x;
+
+                       if (span < 0)
+                               span += PI_TIMES_2;
+
+                       painter->DrawLine(toolPoint[0], toolPoint[3]);
+                       painter->SetBrush(QBrush(Qt::NoBrush));
+                       painter->DrawEllipse(toolPoint[0], toolPoint[1].x, toolPoint[1].x);
+                       painter->SetPen(0xFF00FF, 2.0, LSSolid);
+                       painter->DrawArc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span);
+                       painter->DrawHandle(toolPoint[0] + (Vector(cos(angle), sin(angle)) * toolPoint[1].x));
+                       QString text = tr("Arc span: %1") + QChar(0x00B0);
+                       informativeText = text.arg(RADIANS_TO_DEGREES * span);
+               }
+       }
        else if (Global::tool == TTRotate)
        {
                if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
@@ -743,6 +789,75 @@ void DrawingView::CircleHandler(int mode, Point p)
 }
 
 
+void DrawingView::ArcHandler(int mode, Point p)
+{
+       switch (mode)
+       {
+       case ToolMouseDown:
+               if (Global::toolState == TSNone)
+                       toolPoint[0] = p;
+               else if (Global::toolState == TSPoint2)
+                       toolPoint[1] = p;
+               else if (Global::toolState == TSPoint3)
+                       toolPoint[2] = p;
+               else
+                       toolPoint[3] = p;
+
+               break;
+       case ToolMouseMove:
+               if (Global::toolState == TSNone)
+                       toolPoint[0] = p;
+               else if (Global::toolState == TSPoint2)
+                       toolPoint[1] = p;
+               else if (Global::toolState == TSPoint3)
+                       toolPoint[2] = p;
+               else
+                       toolPoint[3] = p;
+
+               break;
+       case ToolMouseUp:
+               if (Global::toolState == TSNone)
+               {
+                       // Prevent spurious line from drawing...
+                       toolPoint[1] = toolPoint[0];
+                       Global::toolState = TSPoint2;
+               }
+               else if (Global::toolState == TSPoint2)
+               {
+                       if (shiftDown)
+                       {
+                               // Key override is telling us to start circle at new center, not
+                               // continue the current one.
+                               toolPoint[0] = toolPoint[1];
+                               return;
+                       }
+
+                       // Set the radius in toolPoint[1].x
+                       toolPoint[1].x = Vector::Magnitude(toolPoint[0], toolPoint[1]);
+                       Global::toolState = TSPoint3;
+               }
+               else if (Global::toolState == TSPoint3)
+               {
+                       // Set the angle in toolPoint[2].x
+                       toolPoint[2].x = Vector::Angle(toolPoint[0], toolPoint[2]);
+                       Global::toolState = TSPoint4;
+               }
+               else
+               {
+                       double endAngle = Vector::Angle(toolPoint[0], toolPoint[3]);
+                       double span = endAngle - toolPoint[2].x;
+
+                       if (span < 0)
+                               span += PI_TIMES_2;
+
+                       Arc * arc = new Arc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span);
+                       document.objects.push_back(arc);
+                       Global::toolState = TSNone;
+               }
+       }
+}
+
+
 void DrawingView::RotateHandler(int mode, Point p)
 {
        switch (mode)
@@ -1274,6 +1389,34 @@ bool DrawingView::HitTestObjects(Point point)
 
                        break;
                }
+               case OTArc:
+               {
+                       bool oldHP = obj->hitPoint[0], oldHO = obj->hitObject;
+                       obj->hitPoint[0] = obj->hitObject = false;
+                       double length = Vector::Magnitude(obj->p[0], point);
+                       double angle = Vector::Angle(obj->p[0], point);
+
+                       // Make sure we get the angle in the correct spot
+                       if (angle < obj->angle[0])
+                               angle += PI_TIMES_2;
+
+                       // 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...
+
+                       if ((length * Global::zoom) < 8.0)
+                               obj->hitPoint[0] = true;
+                       else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
+                               obj->hitObject = true;
+
+                       obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
+
+                       if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
+                               needUpdate = true;
+
+                       break;
+               }
                default:
                        break;
                }
index c8e46ff627fe6fb70be0d860bbca4efa2c910ce8..e22634c00d936eda7afd7ad2a87752f611e8d5b0 100644 (file)
@@ -28,6 +28,7 @@ class DrawingView: public QWidget
                void ToolDraw(Painter *);
                void LineHandler(int, Point);
                void CircleHandler(int, Point);
+               void ArcHandler(int, Point);
                void RotateHandler(int, Point);
                void CheckObjectBounds(void);
                bool HitTestObjects(Point);
index e0e17c89bf8dd5ce82ce381cfd555051557ee79c..6920e491cb92203f7555a57efc1c1268b209d22c 100644 (file)
@@ -13,7 +13,7 @@ enum DimensionType { DTLinear, DTLinearVert, DTLinearHorz, DTRadial, DTDiametric
 
 enum ToolType { TTNone, TTLine, TTCircle, TTEllipse, TTArc, TTDimension, TTText, TTPolygon, TTSpline, TTRotate, TTMirror, TTTrim, TTTriangulate, TTDelete };
 
-enum ToolState { TSNone, TSPoint1, TSPoint2, TSDone };
+enum ToolState { TSNone, TSPoint1, TSPoint2, TSPoint3, TSPoint4, TSDone };
 
 #define OBJECT_COMMON \
        int type;         \
index a60c1334fd4469897510a350d86c6ccf3d8d37d8..23b429902c2b22b892e25f8ab9cbb57813981f4c 100644 (file)
@@ -243,6 +243,15 @@ bool Vector::isZero(double epsilon/*= 1e-6*/)
 }
 
 
+//
+// Convenience function
+//
+/*static*/ double Vector::Angle(Point p1, Point p2)
+{
+       return Vector(p1, p2).Angle();
+}
+
+
 // Returns the parameter of a point in space to this vector. If the parameter
 // is between 0 and 1, the normal of the vector to the point is on the vector.
 // Note: v1 is the tail, v2 is the head of the line (vector).
index 62438986ef653bd0462d9e600e307105ce592ba3..4bcb461a4a730b459d671852e2b7a633d962af1c 100644 (file)
@@ -13,6 +13,9 @@
 // What we'll do here is create the vector type and use typedef to alias Point
 // to it. Yeah, that's it.
 
+class Vector;
+typedef Vector Point;
+
 class Vector
 {
        public:
@@ -49,6 +52,7 @@ class Vector
 
                static double Dot(Vector v1, Vector v2);
                static double Magnitude(Vector v1, Vector v2);
+               static double Angle(Point p1, Point p2);
                static double Parameter(Vector v1, Vector v2, Vector p);
                static Vector Normal(Vector v1, Vector v2);
                static double AngleBetween(Vector a, Vector b);
@@ -57,6 +61,4 @@ class Vector
                double x, y, z;
 };
 
-typedef Vector Point;
-
 #endif // __VECTOR_H__