1 // trimaction.cpp: Action class for mirroring selected objects
3 // Part of the Architektonas Project
4 // (C) 2011 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 08/27/2011 Created this file
14 #include "trimaction.h"
15 #include "applicationwindow.h"
16 #include "container.h"
17 #include "drawingview.h"
20 #include "mathconstants.h"
24 enum { FIRST_POINT, NEXT_POINT };
27 TrimAction::TrimAction(): state(FIRST_POINT), t(0), u(1.0),
28 doc(&(ApplicationWindow::drawing->document))
30 // shiftWasPressedOnNextPoint(false), ctrlWasPressed(false),
31 // mirror(new Container(Vector()))
33 // ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror);
38 TrimAction::~TrimAction()
43 /*virtual*/ void TrimAction::Draw(Painter * painter)
45 Object * obj = doc->lastObjectHovered;
50 // This assumes a Line, but it might not be!
51 painter->SetPen(QPen(Qt::black, 2.0, Qt::DotLine));
52 Vector v(((Line *)obj)->position, ((Line *)obj)->endpoint);
53 Point p1 = ((Line *)obj)->position + (v * t);
54 Point p2 = ((Line *)obj)->position + (v * u);
55 painter->DrawLine(p1, p2);
57 if (state == FIRST_POINT)
59 painter->DrawHandle(p1);
63 Vector reflectedP2 = -(p2 - p1);
64 Point newP2 = p1 + reflectedP2;
65 painter->DrawLine(newP2, p2);
66 painter->DrawHandle(p1);
68 double absAngle = (Vector(p2 - p1).Angle()) * RADIANS_TO_DEGREES;
70 // Keep the angle between 0 and 180 degrees
74 QString text = QChar(0x2221) + QObject::tr(": %1");
75 text = text.arg(absAngle);
80 painter->DrawInformativeText(text);
82 // Draw the mirror only if there's been a line to mirror around
84 mirror->Draw(painter);
90 /*virtual*/ void TrimAction::MouseDown(Vector /*point*/)
92 // this is not accurate enough. need to use the actual intersection point, not
93 // just the parameter(s).
94 Object * toTrim = doc->lastObjectHovered;
99 //it would be nice to do it like this, but if we bisect the object, we have to
100 //create an extra one...
101 // toTrim->Trim(t, u);
103 Vector v(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint);
105 // Check to see which case we have...
106 // We're trimming point #1...
109 ((Line *)toTrim)->position = ((Line *)toTrim)->position + (v * u);
114 ((Line *)toTrim)->endpoint = ((Line *)toTrim)->position + (v * t);
119 Point p1 = ((Line *)toTrim)->position + (v * t);
120 Point p2 = ((Line *)toTrim)->position + (v * u);
121 Point p3 = ((Line *)toTrim)->endpoint;
122 ((Line *)toTrim)->endpoint = p1;
123 Line * line = new Line(p2, p3);
124 emit ObjectReady(line);
128 doc->lastObjectHovered = NULL;
132 /*virtual*/ void TrimAction::MouseMoved(Vector point)
135 if (state == FIRST_POINT)
140 // mirror->Restore();
141 // mirror->Mirror(p1, p2);
144 // Container & doc = ApplicationWindow::drawing->document;
145 // int items = doc.ItemsSelected();
146 Object * toTrim = doc->lastObjectHovered;
147 // double closestPt1 = 0, closestPt2 = 1.0;
153 if (toTrim->type != OTLine)
156 double pointHoveredT = Geometry::ParameterOfLineAndPoint(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint, point);
158 std::vector<Object *>::iterator i;
160 for(i=doc->objects.begin(); i!=doc->objects.end(); i++)
162 // Can't trim against yourself... :-P
166 Object * trimAgainst = *i;
169 if ((toTrim->type != OTLine) || (trimAgainst->type != OTLine))
172 int intersects = Geometry::Intersects((Line *)toTrim, (Line *)trimAgainst, &t1);//, &u1);
176 // Now what? We don't know which side to trim!
177 // ... now we do, we know which side of the Line we're on!
178 if ((t1 > t) && (t1 < pointHoveredT))
181 if ((t1 < u) && (t1 > pointHoveredT))
188 /*virtual*/ void TrimAction::MouseReleased(void)
191 if (state == FIRST_POINT)
196 else if (state == NEXT_POINT)
201 ApplicationWindow::drawing->document.MirrorSelected(p1, p2);
204 ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror);
209 mirror->CopyContentsTo(&(ApplicationWindow::drawing->document));
216 /*virtual*/ void TrimAction::KeyDown(int /*key*/)
219 if ((key == Qt::Key_Shift) && (state == NEXT_POINT))
221 shiftWasPressedOnNextPoint = true;
227 else if (key == Qt::Key_Control)
229 ctrlWasPressed = true;
233 if ((t == 0) && (u == 1.0))
240 /*virtual*/ void TrimAction::KeyReleased(int /*key*/)
243 if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint)
245 shiftWasPressedOnNextPoint = false;
251 else if (key == Qt::Key_Control)
253 ctrlWasPressed = false;