From 8a5bf49d09b5a00ebea3ffc449519ad05b0326cc Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Sun, 16 Feb 2014 21:15:20 -0600 Subject: [PATCH] Trim tool now works for Lines, but inaccurate. --- src/arc.cpp | 7 +-- src/arc.h | 2 +- src/circle.cpp | 7 +-- src/circle.h | 2 +- src/container.cpp | 11 ++-- src/container.h | 3 +- src/dimension.cpp | 8 +-- src/dimension.h | 2 +- src/line.cpp | 8 +-- src/line.h | 5 +- src/object.cpp | 3 +- src/object.h | 5 +- src/text.h | 2 +- src/trimaction.cpp | 127 +++++++++++++++++++++++++++++++++++++++------ src/trimaction.h | 10 ++-- 15 files changed, 157 insertions(+), 45 deletions(-) diff --git a/src/arc.cpp b/src/arc.cpp index 36245b4..6aefc1c 100644 --- a/src/arc.cpp +++ b/src/arc.cpp @@ -216,7 +216,7 @@ so let's do like this: } -/*virtual*/ void Arc::PointerMoved(Vector point) +/*virtual*/ bool Arc::PointerMoved(Vector point) { // one other thing to check here for is if a modifier key is being held as well, // to allow for multi-selection @@ -229,7 +229,7 @@ so let's do like this: else state = OSInactive; - return; + return false; } // The TLC will send these messages if the object is selected but not clicked on. @@ -239,7 +239,7 @@ so let's do like this: // objectWasDragged = true; // needUpdate = false; SaveHitState(); - HitTest(point); + bool hovered = HitTest(point); needUpdate = HitStateChanged(); objectWasDragged = (draggingCenter | draggingEdge | draggingRotate | draggingSpan); @@ -271,6 +271,7 @@ so let's do like this: // Why save this? For rendering code? oldPoint = point; // needUpdate = true; + return hovered; } diff --git a/src/arc.h b/src/arc.h index bb70776..ec3c600 100644 --- a/src/arc.h +++ b/src/arc.h @@ -12,7 +12,7 @@ class Arc: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool HitTest(Point); virtual void Enumerate(FILE *); diff --git a/src/circle.cpp b/src/circle.cpp index 88cdaa7..94a9ec8 100644 --- a/src/circle.cpp +++ b/src/circle.cpp @@ -118,7 +118,7 @@ Circle::~Circle() } -/*virtual*/ void Circle::PointerMoved(Vector point) +/*virtual*/ bool Circle::PointerMoved(Vector point) { if (selectionInProgress) { @@ -129,13 +129,13 @@ Circle::~Circle() else state = OSInactive; - return; + return false; } // Hit test tells us what we hit (if anything) through boolean variables. It // also tells us whether or not the state changed. SaveHitState(); - HitTest(point); + bool hovered = HitTest(point); needUpdate = HitStateChanged(); objectWasDragged = (draggingEdge | draggingCenter); @@ -149,6 +149,7 @@ Circle::~Circle() // Save this point so the rendering code knows where to draw the handle... dragPoint = point; + return hovered; } diff --git a/src/circle.h b/src/circle.h index 3cf6a44..43b297c 100644 --- a/src/circle.h +++ b/src/circle.h @@ -14,7 +14,7 @@ class Circle: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool HitTest(Point); virtual void Enumerate(FILE *); diff --git a/src/container.cpp b/src/container.cpp index 9cda1fa..2eca9f4 100644 --- a/src/container.cpp +++ b/src/container.cpp @@ -201,9 +201,10 @@ class so that we can leverage that stuff here as well. // into parts and keep subdividing until an acceptable number of objects lie within // the slice. This way, the GUI will still be responsive and *not* have to test // every object for collision. -/*virtual*/ void Container::PointerMoved(Vector point) +/*virtual*/ bool Container::PointerMoved(Vector point) { std::vector::iterator i; + lastObjectHovered = NULL; if (!isTopLevelContainer) { @@ -215,7 +216,7 @@ class so that we can leverage that stuff here as well. else state = OSInactive; - return; + return false; } // No need to do any checking if we're already selected... @@ -253,17 +254,19 @@ class so that we can leverage that stuff here as well. needUpdate = true; } - return; + return false; } for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) { // if (objects[i]->GetState() == OSSelected) - (*i)->PointerMoved(point); + if ((*i)->PointerMoved(point)) + lastObjectHovered = *i; } // Generic container doesn't need this??? // needUpdate = false; + return (lastObjectHovered == NULL ? false : true); } diff --git a/src/container.h b/src/container.h index a9066d6..7de5d89 100644 --- a/src/container.h +++ b/src/container.h @@ -16,7 +16,7 @@ class Container: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool NeedsUpdate(void); virtual void Add(Object *); @@ -49,6 +49,7 @@ class Container: public Object std::vector objects; bool isTopLevelContainer; Object * lastObjectClicked; + Object * lastObjectHovered; private: bool dragging; bool draggingHandle1; diff --git a/src/dimension.cpp b/src/dimension.cpp index 01d7ec3..675afaf 100644 --- a/src/dimension.cpp +++ b/src/dimension.cpp @@ -243,7 +243,7 @@ I believe they are pixels. } -/*virtual*/ void Dimension::PointerMoved(Vector point) +/*virtual*/ bool Dimension::PointerMoved(Vector point) { if (selectionInProgress) { @@ -254,13 +254,13 @@ I believe they are pixels. else state = OSInactive; - return; + return false; } // Hit test tells us what we hit (if anything) through boolean variables. (It // also tells us whether or not the state changed. --not any more) SaveHitState(); - HitTest(point); + bool hovered = HitTest(point); needUpdate = HitStateChanged(); objectWasDragged = (/*draggingLine |*/ draggingHandle1 | draggingHandle2); @@ -278,6 +278,8 @@ I believe they are pixels. oldPoint = point; needUpdate = true; } + + return hovered; } diff --git a/src/dimension.h b/src/dimension.h index 9a9b3d4..dfbfd1d 100644 --- a/src/dimension.h +++ b/src/dimension.h @@ -19,7 +19,7 @@ class Dimension: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool HitTest(Point); virtual void Enumerate(FILE *); diff --git a/src/line.cpp b/src/line.cpp index efd92e5..46a6d85 100644 --- a/src/line.cpp +++ b/src/line.cpp @@ -299,7 +299,7 @@ a dimension only) Draw() function... :-/ } -/*virtual*/ void Line::PointerMoved(Vector point) +/*virtual*/ bool Line::PointerMoved(Vector point) { if (selectionInProgress) { @@ -310,13 +310,13 @@ a dimension only) Draw() function... :-/ else state = OSInactive; - return; + return false; } // Hit test tells us what we hit (if anything) through boolean variables. (It // also tells us whether or not the state changed. --not any more) SaveHitState(); - HitTest(point); + bool hovered = HitTest(point); needUpdate = HitStateChanged(); objectWasDragged = (draggingLine | draggingHandle1 | draggingHandle2); @@ -416,6 +416,8 @@ the horizontal line or vertical line that intersects from the current mouse posi dimPoint2->SetPoint2(draggingHandle2 ? v2 : endpoint); #endif } + + return hovered; } diff --git a/src/line.h b/src/line.h index 70bf398..8c98924 100644 --- a/src/line.h +++ b/src/line.h @@ -16,7 +16,7 @@ class Line: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool HitTest(Point); virtual Vector * GetPointAt(Vector); @@ -38,8 +38,9 @@ class Line: public Object void SaveHitState(void); bool HitStateChanged(void); - protected: + public: Vector endpoint; // Starting point is Object::position + protected: Vector oldPoint; // Used for dragging Point oldEndpoint; diff --git a/src/object.cpp b/src/object.cpp index 09d52bf..2e85bf2 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -75,8 +75,9 @@ printf("Object: Destroyed!\n"); } -/*virtual*/ void Object::PointerMoved(Vector) +/*virtual*/ bool Object::PointerMoved(Vector) { + return false; } diff --git a/src/object.h b/src/object.h index 08b7e9d..f7d5d7c 100644 --- a/src/object.h +++ b/src/object.h @@ -27,7 +27,7 @@ class Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool NeedsUpdate(void); virtual bool HitTest(Point); @@ -62,8 +62,9 @@ class Object static void SetSnapMode(bool state = true); static Vector SnapPointToGrid(Vector); - protected: + public: Vector position; // All objects have a position (doubles as reference point) + protected: Object * parent; //this needs to be added eventually // Pen pen; diff --git a/src/text.h b/src/text.h index a075902..8bba9f8 100644 --- a/src/text.h +++ b/src/text.h @@ -13,7 +13,7 @@ class Text: public Object virtual void Draw(Painter *); virtual Vector Center(void); virtual bool Collided(Vector); - virtual void PointerMoved(Vector); + virtual bool PointerMoved(Vector); virtual void PointerReleased(void); virtual bool HitTest(Point); virtual void Enumerate(FILE *); diff --git a/src/trimaction.cpp b/src/trimaction.cpp index ea8e9eb..40ae9fe 100644 --- a/src/trimaction.cpp +++ b/src/trimaction.cpp @@ -15,6 +15,7 @@ #include "applicationwindow.h" #include "container.h" #include "drawingview.h" +#include "geometry.h" #include "line.h" #include "mathconstants.h" #include "painter.h" @@ -23,12 +24,14 @@ enum { FIRST_POINT, NEXT_POINT }; -TrimAction::TrimAction(): state(FIRST_POINT), line(NULL), - shiftWasPressedOnNextPoint(false), ctrlWasPressed(false), - mirror(new Container(Vector())) +TrimAction::TrimAction(): state(FIRST_POINT), t(0), u(1.0), + doc(&(ApplicationWindow::drawing->document)) +//, line(NULL), +// shiftWasPressedOnNextPoint(false), ctrlWasPressed(false), +// mirror(new Container(Vector())) { - ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror); - mirror->Save(); +// ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror); +// mirror->Save(); } @@ -39,8 +42,18 @@ TrimAction::~TrimAction() /*virtual*/ void TrimAction::Draw(Painter * painter) { - painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); + Object * obj = doc->lastObjectHovered; + if (obj == NULL) + return; + + // This assumes a Line, but it might not be! + painter->SetPen(QPen(Qt::black, 2.0, Qt::DotLine)); + Vector v(((Line *)obj)->position, ((Line *)obj)->endpoint); + Point p1 = ((Line *)obj)->position + (v * t); + Point p2 = ((Line *)obj)->position + (v * u); + painter->DrawLine(p1, p2); +#if 0 if (state == FIRST_POINT) { painter->DrawHandle(p1); @@ -70,36 +83,111 @@ TrimAction::~TrimAction() if (p1 != p2) mirror->Draw(painter); } +#endif } /*virtual*/ void TrimAction::MouseDown(Vector point) { - // Clear our override... - shiftWasPressedOnNextPoint = false; +// this is not accurate enough. need to use the actual intersection point, not +// just the parameter(s). + Object * toTrim = doc->lastObjectHovered; - if (state == FIRST_POINT) - p1 = point; + if (toTrim == NULL) + return; + +//it would be nice to do it like this, but if we bisect the object, we have to +//create an extra one... +// toTrim->Trim(t, u); + + Vector v(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint); + + // Check to see which case we have... + // We're trimming point #1... + if (t == 0) + { + ((Line *)toTrim)->position = ((Line *)toTrim)->position + (v * u); +// u = 1.0; + } + else if (u == 1.0) + { + ((Line *)toTrim)->endpoint = ((Line *)toTrim)->position + (v * t); +// t = 0; + } else - p2 = point; + { + Point p1 = ((Line *)toTrim)->position + (v * t); + Point p2 = ((Line *)toTrim)->position + (v * u); + Point p3 = ((Line *)toTrim)->endpoint; + ((Line *)toTrim)->endpoint = p1; + Line * line = new Line(p2, p3); + emit ObjectReady(line); +// t = 0, u = 1.0; + } + + doc->lastObjectHovered = NULL; } /*virtual*/ void TrimAction::MouseMoved(Vector point) { +#if 0 if (state == FIRST_POINT) p1 = point; - else +// else +// { +// p2 = point; +// mirror->Restore(); +// mirror->Mirror(p1, p2); +// } +#endif +// Container & doc = ApplicationWindow::drawing->document; +// int items = doc.ItemsSelected(); + Object * toTrim = doc->lastObjectHovered; +// double closestPt1 = 0, closestPt2 = 1.0; + t = 0, u = 1.0; + + if (toTrim == NULL) + return; + + if (toTrim->type != OTLine) + return; + + double pointHoveredT = Geometry::ParameterOfLineAndPoint(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint, point); + + std::vector::iterator i; + + for(i=doc->objects.begin(); i!=doc->objects.end(); i++) { - p2 = point; - mirror->Restore(); - mirror->Mirror(p1, p2); + // Can't trim against yourself... :-P + if (*i == toTrim) + continue; + + Object * trimAgainst = *i; + double t1;//, u1; + + if ((toTrim->type != OTLine) || (trimAgainst->type != OTLine)) + continue; + + int intersects = Geometry::Intersects((Line *)toTrim, (Line *)trimAgainst, &t1);//, &u1); + + if (intersects) + { + // Now what? We don't know which side to trim! + // ... now we do, we know which side of the Line we're on! + if ((t1 > t) && (t1 < pointHoveredT)) + t = t1; + + if ((t1 < u) && (t1 > pointHoveredT)) + u = t1; + } } } /*virtual*/ void TrimAction::MouseReleased(void) { +#if 0 if (state == FIRST_POINT) { p2 = p1; @@ -121,11 +209,13 @@ TrimAction::~TrimAction() mirror->CopyContentsTo(&(ApplicationWindow::drawing->document)); } } +#endif } /*virtual*/ void TrimAction::KeyDown(int key) { +#if 0 if ((key == Qt::Key_Shift) && (state == NEXT_POINT)) { shiftWasPressedOnNextPoint = true; @@ -139,11 +229,17 @@ TrimAction::~TrimAction() ctrlWasPressed = true; emit NeedRefresh(); } +#endif + if ((t == 0) && (u == 1.0)) + return; + + t = 0, u = 1.0; } /*virtual*/ void TrimAction::KeyReleased(int key) { +#if 0 if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint) { shiftWasPressedOnNextPoint = false; @@ -157,5 +253,6 @@ TrimAction::~TrimAction() ctrlWasPressed = false; emit NeedRefresh(); } +#endif } diff --git a/src/trimaction.h b/src/trimaction.h index 02720de..78f4425 100644 --- a/src/trimaction.h +++ b/src/trimaction.h @@ -21,11 +21,13 @@ class TrimAction: public Action private: int state; - Line * line; +// Line * line; Vector p1, p2, p1Save; - bool shiftWasPressedOnNextPoint; - bool ctrlWasPressed; - Container * mirror; +// bool shiftWasPressedOnNextPoint; +// bool ctrlWasPressed; +// Container * mirror; + double t, u; + Container * doc; }; #endif // __TRIMACTION_H__ -- 2.37.2