]> Shamusworld >> Repos - architektonas/commitdiff
Added rotation tool.
authorShamus Hammons <jlhamm@acm.org>
Tue, 3 Sep 2013 22:22:38 +0000 (17:22 -0500)
committerShamus Hammons <jlhamm@acm.org>
Tue, 3 Sep 2013 22:22:38 +0000 (17:22 -0500)
16 files changed:
architektonas.pro
src/applicationwindow.cpp
src/arc.cpp
src/arc.h
src/circle.cpp
src/circle.h
src/drawingview.cpp
src/drawingview.h
src/geometry.cpp
src/geometry.h
src/line.cpp
src/line.h
src/object.cpp
src/object.h
src/rotateaction.cpp [new file with mode: 0644]
src/rotateaction.h [new file with mode: 0644]

index 138d12985692bcb23b89bc91a818d837dd40bc4b..edea5ee62184d50c40be368896cf63305a98265f 100644 (file)
@@ -75,6 +75,7 @@ HEADERS = \
        src/mathconstants.h \
        src/object.h \
        src/painter.h \
+       src/rotateaction.h \
        src/settingsdialog.h \
        src/text.h \
        src/vector.h
@@ -108,6 +109,7 @@ SOURCES = \
        src/mirroraction.cpp \
        src/object.cpp \
        src/painter.cpp \
+       src/rotateaction.cpp \
        src/settingsdialog.cpp \
        src/text.cpp \
        src/vector.cpp
index 83dbd54bd1b86f20bc82964473e6641f5900f725..71e8a087d5618225543d37438e1e5b8c23986d53 100644 (file)
@@ -40,6 +40,7 @@
 #include "layerwidget.h"
 #include "mirroraction.h"
 #include "painter.h"
+#include "rotateaction.h"
 #include "settingsdialog.h"
 
 
@@ -401,7 +402,6 @@ void ApplicationWindow::SetInternalToolStates(void)
 {
        Object::SetDeleteActive(deleteAct->isChecked());
        Object::SetDimensionActive(addDimensionAct->isChecked());
-       drawing->SetRotateToolActive(rotateAct->isChecked());
 
        // We can be sure that if we've come here, then either an active tool is
        // being deactivated, or a new tool is being created. In either case, the
@@ -413,23 +413,17 @@ void ApplicationWindow::SetInternalToolStates(void)
                Object::ignoreClicks = false;
        }
 
-#if 0
-       drawing->SetAddLineToolActive(addLineAct->isChecked());
-       drawing->SetAddCircleToolActive(addCircleAct->isChecked());
-       drawing->SetAddArcToolActive(addArcAct->isChecked());
-       drawing->SetAddDimensionToolActive(addDimensionAct->isChecked());
-#else
        drawing->SetToolActive(addLineAct->isChecked() ? new DrawLineAction() : NULL);
        drawing->SetToolActive(addCircleAct->isChecked() ? new DrawCircleAction() : NULL);
        drawing->SetToolActive(addArcAct->isChecked() ? new DrawArcAction() : NULL);
        drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL);
        drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
-#endif
+       drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL);
 
        if (drawing->toolAction)
                Object::ignoreClicks = true;
 
-       update();
+       drawing->update();
 }
 
 
index f7cde5283c8befbf01926979e787d9afa1aa8c6b..e4a6b6f4788de7b89f1196fa75a8018217fad421 100644 (file)
@@ -456,6 +456,18 @@ same reference number.
 }
 
 
+/*virtual*/ void Arc::Rotate(Point point, double angle)
+{
+       Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
+       Point ap1(cos(startAngle), sin(startAngle));
+       Point angleStartPoint = (ap1 * radius) + position;
+       Point c2 = Geometry::RotatePointAroundPoint(angleStartPoint, point, angle);
+
+       position = c1;
+       startAngle = Vector(c2, c1).Angle();
+}
+
+
 /*virtual*/ void Arc::Mirror(Point p1, Point p2)
 {
        Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
index da0a6ea674375e037bbe33807ef4bf4544824504..bb707768b24eb2695de4af5f0281926d0ba630ef 100644 (file)
--- a/src/arc.h
+++ b/src/arc.h
@@ -18,6 +18,7 @@ class Arc: public Object
                virtual void Enumerate(FILE *);
                virtual Object * Copy(void);
                virtual QRectF Extents(void);
+               virtual void Rotate(Point, double);
                virtual void Mirror(Point, Point);
                virtual void Save(void);
                virtual void Restore(void);
index b722f4d390a3c290ec6a68338b6591ebc061497a..d8a2e5d61bda7faa31c349546a7b94c79d0771c1 100644 (file)
@@ -243,6 +243,13 @@ same reference number.
 }
 
 
+/*virtual*/ void Circle::Rotate(Point point, double angle)
+{
+       Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
+       position = c1;
+}
+
+
 /*virtual*/ void Circle::Mirror(Point p1, Point p2)
 {
        Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
index 6fd22cd615dcbeb89fc3f61381206babe0631bee..527ea0f0d472f34ceb7afde04c4754344a6195f0 100644 (file)
@@ -18,6 +18,7 @@ class Circle: public Object
                virtual void Enumerate(FILE *);
                virtual Object * Copy(void);
                virtual QRectF Extents(void);
+               virtual void Rotate(Point, double);
                virtual void Mirror(Point, Point);
                virtual void Save(void);
                virtual void Restore(void);
index 3020368913cfa3b4358df95669b1b65649523d15..89c63ed429d9a95f71aa245160d09d95c6ca7e4b 100644 (file)
@@ -19,6 +19,7 @@
 //
 // STILL TO BE DONE:
 //
+// - Lots of stuff
 //
 
 // Uncomment this for debugging...
@@ -47,8 +48,8 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10),
        document(Vector(0, 0)),
-       /*gridSpacing(12.0),*/ gridPixels(0), collided(false), rotateTool(false),
-       rx(150.0), ry(150.0),
+       /*gridSpacing(12.0),*/ gridPixels(0), collided(false), //rotateTool(false),
+//     rx(150.0), ry(150.0),
 //     scrollDrag(false), addLineTool(false), addCircleTool(false),
 //     addDimensionTool(false),
        toolAction(NULL)
@@ -130,13 +131,6 @@ we do! :-)
 }
 
 
-void DrawingView::SetRotateToolActive(bool state/*= true*/)
-{
-       rotateTool = state;
-       update();
-}
-
-
 void DrawingView::SetToolActive(Action * action)
 {
        if (action != NULL)
@@ -291,28 +285,6 @@ QPoint DrawingView::GetAdjustedClientPosition(int x, int y)
 }
 
 
-#if 0
-//
-// This looks strange, but it's really quite simple: We want a point that's
-// more than half-way to the next grid point to snap there while conversely we
-// want a point that's less than half-way to to the next grid point then snap
-// to the one before it. So we add half of the grid spacing to the point, then
-// divide by it so that we can remove the fractional part, then multiply it
-// back to get back to the correct answer.
-//
-Vector DrawingView::SnapPointToGrid(Vector point)
-{
-       point += gridSpacing / 2.0;             // *This* adds to Z!!!
-       point /= gridSpacing;
-       point.x = floor(point.x);//need to fix this for negative numbers...
-       point.y = floor(point.y);
-       point.z = 0;                                    // Make *sure* Z doesn't go anywhere!!!
-       point *= gridSpacing;
-       return point;
-}
-#endif
-
-
 void DrawingView::paintEvent(QPaintEvent * /*event*/)
 {
        QPainter qtPainter(this);
@@ -321,35 +293,18 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
        if (useAntialiasing)
                qtPainter.setRenderHint(QPainter::Antialiasing);
 
-//     Painter::screenSize = Vector(size().width(), size().height());
        Object::SetViewportHeight(size().height());
 
        // Draw coordinate axes
-
        painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
        painter.DrawLine(0, -16384, 0, 16384);
        painter.DrawLine(-16384, 0, 16384, 0);
 
-       // Draw supplemental (tool related) points
-// NOTE that this can be done as an action!
-// In that case, we would need access to the document...
-// [We can do that by making the document a class object...]
-       if (rotateTool)
-       {
-               painter.SetPen(QPen(QColor(0, 200, 0), 2.0, Qt::SolidLine));
-               painter.DrawLine(rx - 10, ry, rx + 10, ry);
-               painter.DrawLine(rx, ry - 10, rx, ry + 10);
-       }
-
-// Maybe we can make the grid into a background brush instead, and let Qt deal
-// with it??? YES!!
-
        // The top level document takes care of rendering for us...
        document.Draw(&painter);
 
        if (toolAction)
        {
-//             painter.SetPen(QPen(Qt::green, 1.0, Qt::DashLine));
                painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
                painter.DrawCrosshair(oldPoint);
                toolAction->Draw(&painter);
@@ -357,9 +312,7 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
 
        if (Object::selectionInProgress)
        {
-//             painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
                painter.SetPen(QPen(QColor(255, 127, 0, 255)));
-//             painter.SetBrush(QBrush(Qt::NoBrush));
                painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
                painter.DrawRect(Object::selection);
        }
index 55384fa48a3c7c686abc5ba2d44b46dd2d961718..bd3e07e43307fe4d1256fa4898d70a683a243390 100644 (file)
@@ -14,7 +14,7 @@ class DrawingView: public QWidget
                DrawingView(QWidget * parent = NULL);
 
        public:
-               void SetRotateToolActive(bool state = true);
+//             void SetRotateToolActive(bool state = true);
                void SetToolActive(Action * action);
                void SetGridSize(uint32_t);
                void UpdateGridBackground(void);
@@ -50,8 +50,8 @@ class DrawingView: public QWidget
                bool collided;
 //Should this go into Object's class variables???
 //maybe, maybe not... :-P
-               bool rotateTool;
-               double rx, ry;
+//             bool rotateTool;
+//             double rx, ry;
                bool scrollDrag;
                Vector oldPoint;
 //             bool addLineTool;
index fdceb8eff6a332f618f83b2a334e6c38a84a4323..5f9a30b964f07348db24af44482508c52bacf668 100644 (file)
@@ -14,7 +14,7 @@
 //
 
 #include "geometry.h"
-
+#include <math.h>
 
 Point Geometry::IntersectionOfLineAndLine(Point p1, Point p2, Point p3, Point p4)
 {
@@ -76,3 +76,13 @@ Point Geometry::MirrorPointAroundLine(Point point, Point p1, Point p2)
        return mirroredPoint;
 }
 
+
+Point Geometry::RotatePointAroundPoint(Point point, Point rotationPoint, double angle)
+{
+       Vector v = Vector(point, rotationPoint);
+       double px = (v.x * cos(angle)) - (v.y * sin(angle));
+       double py = (v.x * sin(angle)) + (v.y * cos(angle));
+
+       return Vector(rotationPoint.x + px, rotationPoint.y + py, 0);
+}
+
index d2ec82b0590f408fcdf2f91c0a54d3cddcc181f8..6ff456410aa22ba01682128cd17a8392707c2a3b 100644 (file)
@@ -10,6 +10,7 @@ class Geometry
                static Point IntersectionOfLineAndLine(Point, Point, Point, Point);
                static double ParameterOfLineAndPoint(Point, Point, Point);
                static Point MirrorPointAroundLine(Point, Point, Point);
+               static Point RotatePointAroundPoint(Point, Point, double);
 };
 
 #endif         // __GEOMETRY_H__
index b7abc9ad6bb62939cb9ddd5102a65d25d7bcadf3..90b5dc21e96485391fcaad161d1147d54c98912c 100644 (file)
@@ -123,6 +123,11 @@ Line::~Line()
 
 /*virtual*/ bool Line::Collided(Vector point)
 {
+/*
+what we can do here is set ignoreClicks to true to keep other objects that are
+selected from deselecting themselves. Will that fuck up something else? Not sure
+yet... :-/
+*/
        // Someone told us to fuck off, so we'll fuck off. :-)
        if (ignoreClicks)
                return false;
@@ -571,12 +576,16 @@ same reference number.
 }
 
 
-/*virtual*/ void Line::Rotate(Vector point, double angle)
+/*virtual*/ void Line::Rotate(Point point, double angle)
 {
+       Point l1 = Geometry::RotatePointAroundPoint(position, point, angle);
+       Point l2 = Geometry::RotatePointAroundPoint(endpoint, point, angle);
+       position = l1;
+       endpoint = l2;
 }
 
 
-/*virtual*/ void Line::Scale(Vector point, double amount)
+/*virtual*/ void Line::Scale(Point point, double amount)
 {
 }
 
index 5d84b39bf9128ab1bf69f27bea9ec5ed2660b5af..4e5d7b59e50c28bd8822066bf6fe4a30a5927db9 100644 (file)
@@ -23,7 +23,7 @@ class Line: public Object
                virtual Vector GetPointAtParameter(double parameter);
                virtual QRectF Extents(void);
                virtual void Translate(Vector);
-               virtual void Rotate(Vector, double);
+               virtual void Rotate(Point, double);
                virtual void Scale(Vector, double);
                virtual void Mirror(Point, Point);
                virtual void Save(void);
index a3ff1ac945705dd427f18bce3c988a52fe4cadc4..ca065dcdc77832daa41192d3d7496739d68a193e 100644 (file)
@@ -224,12 +224,12 @@ printf("Object: Destroyed!\n");
 }
 
 
-/*virtual*/ void Object::Rotate(Vector, double)
+/*virtual*/ void Object::Rotate(Point, double)
 {
 }
 
 
-/*virtual*/ void Object::Scale(Vector, double)
+/*virtual*/ void Object::Scale(Point, double)
 {
 }
 
index d34e79ae7598df74e85b3d330f63a390a9aeafe4..ec775d16fbf42fd1443bec267375bddb3d984f63 100644 (file)
@@ -42,8 +42,8 @@ class Object
                virtual QRectF Extents(void);
 //             virtual ObjectType Type(void);// = 0; // Pure virtual, must be implemented
                virtual void Translate(Vector);
-               virtual void Rotate(Vector, double);
-               virtual void Scale(Vector, double);
+               virtual void Rotate(Point, double);
+               virtual void Scale(Point, double);
                virtual void Mirror(Point, Point);
                virtual void Save(void);
                virtual void Restore(void);
diff --git a/src/rotateaction.cpp b/src/rotateaction.cpp
new file mode 100644 (file)
index 0000000..661e617
--- /dev/null
@@ -0,0 +1,167 @@
+// rotateaction.cpp: Action class for rotating selected objects
+//
+// Part of the Architektonas Project
+// (C) 2011 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  09/03/2011  Created this file
+//
+
+#include "rotateaction.h"
+#include "applicationwindow.h"
+#include "container.h"
+#include "drawingview.h"
+#include "line.h"
+#include "mathconstants.h"
+#include "painter.h"
+//#include "vector.h"
+
+
+//#define FIRST_POINT 0
+//#define NEXT_POINT 1
+enum { FIRST_POINT, NEXT_POINT };
+
+
+RotateAction::RotateAction(): state(FIRST_POINT), line(NULL),
+       shiftWasPressedOnNextPoint(false), spin(new Container(Vector()))
+{
+//     ApplicationWindow::drawing->document.CopySelectedContentsTo(selected);
+       ApplicationWindow::drawing->document.CopySelectedContentsTo(spin);
+
+//     for(std::vector<Object *>::iterator i=spin->objects.begin(); i!=spin->objects.end(); i++)
+//             (*i)->Save();
+       spin->Save();
+}
+
+
+RotateAction::~RotateAction()
+{
+}
+
+
+/*virtual*/ void RotateAction::Draw(Painter * painter)
+{
+       painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
+
+       // I think stuff like crosshairs should be done in the DrawingView, tho
+       // (and it's done there now...)
+       if (state == FIRST_POINT)
+       {
+               painter->DrawHandle(p1);
+       }
+       else
+       {
+//             Vector reflectedP2 = -(p2 - p1);
+//             Point newP2 = p1 + reflectedP2;
+               painter->DrawLine(p1, p2);
+               painter->DrawHandle(p1);
+
+               double absAngle = (Vector(p2 - p1).Angle()) * RADIANS_TO_DEGREES;
+
+               // Keep the angle between 0 and 180 degrees
+//             if (absAngle > 180.0)
+//                     absAngle -= 180.0;
+
+               QString text = QChar(0x2221) + QObject::tr(": %1");
+               text = text.arg(absAngle);
+//             QString text = tr("Length: %1 in.");
+//             text = text.arg(Vector::Magnitude(p1, p2));
+               painter->DrawInformativeText(text);
+
+               // Draw the rotated objects only if there's been a line to spin around
+               if (p1 != p2)
+                       spin->Draw(painter);
+       }
+}
+
+
+/*virtual*/ void RotateAction::MouseDown(Vector point)
+{
+       // Clear our override...
+       shiftWasPressedOnNextPoint = false;
+
+       if (state == FIRST_POINT)
+               p1 = point;
+       else
+               p2 = point;
+}
+
+
+/*virtual*/ void RotateAction::MouseMoved(Vector point)
+{
+       if (state == FIRST_POINT)
+               p1 = point;
+       else
+       {
+               p2 = point;
+               double angle = Vector(p2, p1).Angle();
+
+               for(std::vector<Object *>::iterator i=spin->objects.begin(); i!=spin->objects.end(); i++)
+               {
+                       (*i)->Restore();
+                       (*i)->Rotate(p1, angle);
+               }
+       }
+}
+
+
+/*virtual*/ void RotateAction::MouseReleased(void)
+{
+       if (state == FIRST_POINT)
+       {
+               p2 = p1;
+               state = NEXT_POINT;
+       }
+       else if (state == NEXT_POINT)
+       {
+               state = FIRST_POINT;
+
+               std::vector<Object *> & objs = ApplicationWindow::drawing->document.objects;
+               double angle = Vector(p2, p1).Angle();
+
+               for(std::vector<Object *>::iterator i=objs.begin(); i!=objs.end(); i++)
+               {
+                       if ((*i)->state == OSSelected)
+                               (*i)->Rotate(p1, angle);
+               }
+
+               spin->Clear();
+               ApplicationWindow::drawing->document.CopySelectedContentsTo(spin);
+               spin->Save();
+       }
+}
+
+
+/*virtual*/ bool RotateAction::KeyDown(int key)
+{
+       if ((key == Qt::Key_Shift) && (state == NEXT_POINT))
+       {
+               shiftWasPressedOnNextPoint = true;
+               p1Save = p1;
+               p1 = p2;
+               state = FIRST_POINT;
+               return true;
+       }
+
+       return false;
+}
+
+
+/*virtual*/ bool RotateAction::KeyReleased(int key)
+{
+       if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint)
+       {
+               shiftWasPressedOnNextPoint = false;
+               p2 = p1;
+               p1 = p1Save;
+               state = NEXT_POINT;
+               return true;
+       }
+
+       return false;
+}
+
diff --git a/src/rotateaction.h b/src/rotateaction.h
new file mode 100644 (file)
index 0000000..91a9bdd
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __ROTATEACTION_H__
+#define __ROTATEACTION_H__
+
+#include "action.h"
+
+class Container;
+class Line;
+
+class RotateAction: public Action
+{
+       public:
+               RotateAction();
+               ~RotateAction();
+
+               virtual void Draw(Painter *);
+               virtual void MouseDown(Vector);
+               virtual void MouseMoved(Vector);
+               virtual void MouseReleased(void);
+               virtual bool KeyDown(int);
+               virtual bool KeyReleased(int);
+
+       private:
+               int state;
+               Line * line;
+               Point p1, p2, p1Save;
+               bool shiftWasPressedOnNextPoint;
+//             Container * selected;
+               Container * spin;
+};
+
+#endif // __ROTATEACTION_H__
+