]> Shamusworld >> Repos - architektonas/commitdiff
Added Geometry class for common geometric tools used everywhere.
authorShamus Hammons <jlhamm@acm.org>
Sat, 31 Aug 2013 21:35:06 +0000 (16:35 -0500)
committerShamus Hammons <jlhamm@acm.org>
Sat, 31 Aug 2013 21:35:06 +0000 (16:35 -0500)
architektonas.pro
src/applicationwindow.cpp
src/geometry.cpp [new file with mode: 0644]
src/geometry.h [new file with mode: 0644]
src/line.cpp
src/mirroraction.cpp
src/mirroraction.h
src/vector.cpp

index 54e428ea04f38e9f88c818c79caef942722b38d2..138d12985692bcb23b89bc91a818d837dd40bc4b 100644 (file)
@@ -66,6 +66,7 @@ HEADERS = \
        src/ellipse.h \
        src/fileio.h \
        src/generaltab.h \
+       src/geometry.h \
        src/layerwidget.h \
        src/layeritemwidget.h \
        src/line.h \
@@ -99,6 +100,7 @@ SOURCES = \
        src/ellipse.cpp \
        src/fileio.cpp \
        src/generaltab.cpp \
+       src/geometry.cpp \
        src/layerwidget.cpp \
        src/layeritemwidget.cpp \
        src/line.cpp \
index 445e546d01e36775abbcecb0c3170f0f988ce42b..83dbd54bd1b86f20bc82964473e6641f5900f725 100644 (file)
@@ -410,6 +410,7 @@ void ApplicationWindow::SetInternalToolStates(void)
        {
                delete drawing->toolAction;
                drawing->toolAction = NULL;
+               Object::ignoreClicks = false;
        }
 
 #if 0
@@ -425,6 +426,9 @@ void ApplicationWindow::SetInternalToolStates(void)
        drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL);
 #endif
 
+       if (drawing->toolAction)
+               Object::ignoreClicks = true;
+
        update();
 }
 
diff --git a/src/geometry.cpp b/src/geometry.cpp
new file mode 100644 (file)
index 0000000..fdceb8e
--- /dev/null
@@ -0,0 +1,78 @@
+// geometry.cpp: Algebraic geometry helper functions
+//
+// 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  08/31/2011  Created this file
+//
+// NOTE: All methods in this class are static.
+//
+
+#include "geometry.h"
+
+
+Point Geometry::IntersectionOfLineAndLine(Point p1, Point p2, Point p3, Point p4)
+{
+       // Find the intersection of the lines by formula:
+       // px = (x1y2 - y1x2)(x3 - x4) - (x1 - x2)(x3y4 - y3x4)
+       // py = (x1y2 - y1x2)(y3 - y4) - (y1 - y2)(x3y4 - y3x4)
+       // d = (x1 - x2)(y3 - y4) - (y1 - y2)(x3 - x4) = 0 if lines are parallel
+       // Intersection is (px / d, py / d)
+
+       double d = ((p1.x - p2.x) * (p3.y - p4.y)) - ((p1.y - p2.y) * (p3.x - p4.x));
+
+       // Check for parallel lines, and return sentinel if so
+       if (d == 0)
+               return Point(0, 0, -1);
+
+       double px = (((p1.x * p2.y) - (p1.y * p2.x)) * (p3.x - p4.x))
+               - ((p1.x - p2.x) * ((p3.x * p4.y) - (p3.y * p4.x)));
+       double py = (((p1.x * p2.y) - (p1.y * p2.x)) * (p3.y - p4.y))
+               - ((p1.y - p2.y) * ((p3.x * p4.y) - (p3.y * p4.x)));
+
+       return Point(px / d, py / d, 0);
+}
+
+
+// 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.
+double Geometry::ParameterOfLineAndPoint(Point lp1, Point lp2, Point point)
+{
+       // Geometric interpretation:
+       // The parameterized point on the vector lineSegment is where the normal of
+       // the lineSegment to the point intersects lineSegment. If the pp < 0, then
+       // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the
+       // perpendicular lies beyond the 2nd endpoint.
+
+       Vector lineSegment = lp1 - lp2;
+       double magnitude = lineSegment.Magnitude();
+       Vector pointSegment = point - lp2;
+       double t = lineSegment.Dot(pointSegment) / (magnitude * magnitude);
+       return t;
+}
+
+
+Point Geometry::MirrorPointAroundLine(Point point, Point p1, Point p2)
+{
+       // Get the vector of the intersection of the line and the normal on the
+       // line to the point in question.
+       double t = ParameterOfLineAndPoint(p1, p2, point);
+       Vector v = Vector(p1, p2) * t;
+
+       // Get the point normal to point to the line passed in (p2 is the tail)
+       Point normalOnLine = p2 + v;
+
+       // Make our mirrored vector (head - tail)
+       Vector mirror = -(point - normalOnLine);
+
+       // Find the mirrored point
+       Point mirroredPoint = normalOnLine + mirror;
+
+       return mirroredPoint;
+}
+
diff --git a/src/geometry.h b/src/geometry.h
new file mode 100644 (file)
index 0000000..d2ec82b
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __GEOMETRY_H__
+#define __GEOMETRY_H__
+
+#include "vector.h"
+
+class Geometry
+{
+       public:
+               // All methods are class methods for this class
+               static Point IntersectionOfLineAndLine(Point, Point, Point, Point);
+               static double ParameterOfLineAndPoint(Point, Point, Point);
+               static Point MirrorPointAroundLine(Point, Point, Point);
+};
+
+#endif         // __GEOMETRY_H__
+
index 8425e62356e5062cee58b39a50da4793e0c11090..956b9bdd3c7174c16041885ed43100e758f2ff67 100644 (file)
@@ -21,6 +21,7 @@
 #include <QtGui>
 #include "container.h"
 #include "dimension.h"
+#include "geometry.h"
 #include "mathconstants.h"
 #include "painter.h"
 
@@ -122,6 +123,10 @@ Line::~Line()
 
 /*virtual*/ bool Line::Collided(Vector point)
 {
+       // Someone told us to fuck off, so we'll fuck off. :-)
+       if (ignoreClicks)
+               return false;
+
        // We can assume this, since this is a mouse down event here.
        objectWasDragged = false;
        HitTest(point);
@@ -445,7 +450,8 @@ the horizontal line or vertical line that intersects from the current mouse posi
        Vector lineSegment = endpoint - position;
        Vector v1 = point - position;
        Vector v2 = point - endpoint;
-       double t = Vector::Parameter(position, endpoint, point);
+//     double t = Vector::Parameter(position, endpoint, point);
+       double t = Geometry::ParameterOfLineAndPoint(position, endpoint, point);
        double distance;
 
        // Geometric interpretation:
@@ -577,52 +583,55 @@ same reference number.
 
 /*virtual*/ Object * Line::Mirror(Vector p1, Vector p2)
 {
-#if 0
-       return NULL;
+#if 1
+       Point l1 = Geometry::MirrorPointAroundLine(position, p1, p2);
+       Point l2 = Geometry::MirrorPointAroundLine(endpoint, p1, p2);
+       return new Line(l1, l2);
+#else
+       Vector normal = Vector::Normal(p1, p2);
+       Vector p4 = position + normal;
 
-double Vector::Parameter(Vector v1, Vector v2, Vector p)
-{
-       // Geometric interpretation:
-       // The parameterized point on the vector lineSegment is where the normal of
-       // the lineSegment to the point intersects lineSegment. If the pp < 0, then
-       // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the
-       // perpendicular lies beyond the 2nd endpoint.
-
-       Vector lineSegment = v2 - v1;
-       double magnitude = lineSegment.Magnitude();
-       Vector pointSegment = p - v1;
-       double t = lineSegment.Dot(pointSegment) / (magnitude * magnitude);
-       return t;
-}
+       // Find the intersection of the line and position + normal to the line
+       double px = (((p1.x * p2.y) - (p1.y * p2.x)) * (position.x - p4.x))
+               - ((p1.x - p2.x) * ((position.x * p4.y) - (position.y * p4.x)));
+       double py = (((p1.x * p2.y) - (p1.y * p2.x)) * (position.y - p4.y))
+               - ((p1.y - p2.y) * ((position.x * p4.y) - (position.y * p4.x)));
+       double d = ((p1.x - p2.x) * (position.y - p4.y))
+               - ((p1.y - p2.y) * (position.x - p4.x));
 
+       // px = (x1y2 - y1x2)(x3 - x4) - (x1 - x2)(x3y4 - y3x4)
+       // py = (x1y2 - y1x2)(y3 - y4) - (y1 - y2)(x3y4 - y3x4)
+       // d = (x1 - x2)(y3 - y4) - (y1 - y2)(x3 - x4) = 0 if lines are parallel
+       // Intersection is (px / d, py / d)
 
-// Return the normal to the linesegment formed by the passed in points.
-// (Not sure which is head or tail, or which hand the normal lies)
-/*static*/ Vector Vector::Normal(Vector v1, Vector v2)
-#endif
+       Vector v1(px / d, py / d);
 
-       double t1 = Vector::Parameter(p1, p2, position);
-       double t2 = Vector::Parameter(p1, p2, endpoint);
+//     Vector normal = Vector::Normal(p1, p2);
+       p4 = endpoint + normal;
 
-       Vector unit = Vector(p1, p2).Unit();
-       Vector v1 = unit * t1;
-       Vector v2 = unit * t2;
+       // Find the intersection of the line and endpoint + normal to the line
+       px = (((p1.x * p2.y) - (p1.y * p2.x)) * (endpoint.x - p4.x))
+               - ((p1.x - p2.x) * ((endpoint.x * p4.y) - (endpoint.y * p4.x)));
+       py = (((p1.x * p2.y) - (p1.y * p2.x)) * (endpoint.y - p4.y))
+               - ((p1.y - p2.y) * ((endpoint.x * p4.y) - (endpoint.y * p4.x)));
+       d = ((p1.x - p2.x) * (endpoint.y - p4.y))
+               - ((p1.y - p2.y) * (endpoint.x - p4.x));
 
-//     Vector normal = Vector::Normal(p1, p2);
-       // Get the points normal to position & endpoint to the line passed in
-       // (these are tails)
-       Vector v3 = p1 + v1;
-       Vector v4 = p1 + v2;
+       Vector v2(px / d, py / d);
 
-       // Make our mirrored vectors
-       Vector v5 = -(position - v3);
-       Vector v6 = -(endpoint - v4);
+#if 0
+       Vector v3 = position - v1;
+       Vector v4 = endpoint - v2;
 
-       // Find the points
-       Vector v7 = v3 + v5;
-       Vector v8 = v4 + v6;
+       Vector v5 = v1 + -v3;
+       Vector v6 = v2 + -v4;
+#else
+       Vector v5 = v1 + v1 - position;
+       Vector v6 = v2 + v2 - endpoint;
+#endif
 
-       return new Line(v7, v8);
+       return new Line(v5, v6);
+#endif
 }
 
 
index 998a0e1f16b5f90344e355d1423b59b0fa44c3c4..720692ed85130725ac3c2170206fa2ec251463ea 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "mirroraction.h"
 #include "applicationwindow.h"
+#include "container.h"
+#include "drawingview.h"
 #include "line.h"
 #include "mathconstants.h"
 #include "painter.h"
@@ -25,7 +27,7 @@ enum { FIRST_POINT, NEXT_POINT };
 
 
 MirrorAction::MirrorAction(): state(FIRST_POINT), line(NULL),
-       shiftWasPressedOnNextPoint(false)
+       shiftWasPressedOnNextPoint(false), mirror(new Container(Vector()))
 {
 }
 
@@ -58,6 +60,8 @@ MirrorAction::~MirrorAction()
 //             QString text = tr("Length: %1 in.");
 //             text = text.arg(Vector::Magnitude(p1, p2));
                painter->DrawInformativeText(text);
+
+               mirror->Draw(painter);
        }
 }
 
@@ -81,6 +85,19 @@ MirrorAction::~MirrorAction()
        else
        {
                p2 = point;
+
+               mirror->Clear();
+               int itemsSelected = ApplicationWindow::drawing->document.ItemsSelected();
+
+               if (itemsSelected == 0)
+                       return;
+
+               for(int i=0; i<itemsSelected; i++)
+               {
+                       Object * object = ApplicationWindow::drawing->document.SelectedItem(i);
+                       Object * mirrored = object->Mirror(p1, p2);
+                       mirror->Add(mirrored);
+               }
        }
 }
 
index 0ff0a79cc8d7ed2df63ec361287820d49663f732..2198a88e4a6543220b91a07cefb0477c0abcdc3d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "action.h"
 
+class Container;
 class Line;
 
 class MirrorAction: public Action
@@ -23,6 +24,7 @@ class MirrorAction: public Action
                Line * line;
                Vector p1, p2, p1Save;
                bool shiftWasPressedOnNextPoint;
+               Container * mirror;
 };
 
 #endif // __MIRRORACTION_H__
index 23bd783cf2fcce61dd3c6ab6627972ca7678813a..ac5a2058191e4f7e11d24218ba8085e93d7372d8 100644 (file)
@@ -244,9 +244,9 @@ double Vector::Parameter(Vector v1, Vector v2, Vector p)
        // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the\r
        // perpendicular lies beyond the 2nd endpoint.\r
 \r
-       Vector lineSegment = v2 - v1;\r
+       Vector lineSegment = v1 - v2;\r
        double magnitude = lineSegment.Magnitude();\r
-       Vector pointSegment = p - v1;\r
+       Vector pointSegment = p - v2;\r
        double t = lineSegment.Dot(pointSegment) / (magnitude * magnitude);\r
        return t;\r
 }\r
@@ -256,7 +256,7 @@ double Vector::Parameter(Vector v1, Vector v2, Vector p)
 // (Not sure which is head or tail, or which hand the normal lies)\r
 /*static*/ Vector Vector::Normal(Vector v1, Vector v2)\r
 {\r
-       Vector v = (v2 - v1).Unit();\r
+       Vector v = (v1 - v2).Unit();\r
        return Vector(-v.y, v.x);\r
 }\r
 \r