]> Shamusworld >> Repos - architektonas/commitdiff
Fixed missing edge cases in line to line intersection function.
authorShamus Hammons <jlhamm@acm.org>
Wed, 5 Feb 2014 20:36:01 +0000 (14:36 -0600)
committerShamus Hammons <jlhamm@acm.org>
Wed, 5 Feb 2014 20:36:01 +0000 (14:36 -0600)
src/applicationwindow.cpp
src/dimension.cpp
src/dimension.h
src/geometry.cpp
src/geometry.h

index 23629bca9976e3ef78a5780e5b45d4da6169bada..effcc1eb59904eefedb95ec5a66f019ea0e8a9e8 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "about.h"
 #include "blockwidget.h"
+#include "dimension.h"
 #include "drawingview.h"
 #include "drawarcaction.h"
 #include "drawcircleaction.h"
@@ -39,6 +40,7 @@
 #include "generaltab.h"
 #include "geometry.h"
 #include "layerwidget.h"
+#include "line.h"
 #include "mirroraction.h"
 #include "painter.h"
 #include "rotateaction.h"
@@ -529,20 +531,39 @@ void ApplicationWindow::HandleConnection(void)
                for(int j=i+1; j<itemsSelected; j++)
                {
                        Object * obj2 = drawing->document.SelectedItem(j);
-                       double t, u;
+                       double t, u, v, w;
 
-                       if ((obj1->type != OTLine) || (obj2->type != OTLine))
-                               continue;
+//                     if ((obj1->type != OTLine) || (obj2->type != OTLine))
+//                             continue;
 
+                       if ((obj1->type == OTLine) && (obj2->type == OTLine))
+                       {
 //printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
-                       int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
+                               int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
 //printf("  (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
 
-                       if (intersects)
+                               if (intersects)
+                               {
+       //printf("Connecting objects (%X, %X)...\n", obj1, obj2);
+                                       obj1->Connect(obj2, u);
+                                       obj2->Connect(obj1, t);
+                               }
+                       }
+                       else if (((obj1->type == OTLine) && (obj2->type == OTDimension))
+                               || ((obj2->type == OTLine) && (obj1->type == OTDimension)))
                        {
-printf("Connecting objects (%X, %X)...\n", obj1, obj2);
-                               obj1->Connect(obj2, u);
-                               obj2->Connect(obj1, t);
+printf("Testing Line<->Dimension intersection...\n");
+                               Line * line = (Line *)(obj1->type == OTLine ? obj1 : obj2);
+                               Dimension * dim = (Dimension *)(obj1->type == OTDimension ? obj1 : obj2);
+
+                               int intersects = Geometry::Intersects(line, dim, &t, &u);
+printf("   -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u);
+
+                               if (intersects)
+                               {
+                                       obj1->Connect(obj2, u);
+                                       obj2->Connect(obj1, t);
+                               }
                        }
                }
        }
index b3f1e7f3d915d0392c37abe7c2d01b8826b13b95..27823b39135fb8f7f7ed87f4d482476672a42b19 100644 (file)
@@ -78,9 +78,9 @@ all objects move as a unified whole.
 
        if ((state == OSSelected) || ((state == OSInactive) && hitPoint2))
                painter->DrawHandle(endpoint);
-#if 0
+#if 1
        if (state == OSSelected)
-               painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
+               painter->SetPen(QPen(Qt::cyan, 1.0 * Painter::zoom * size, Qt::SolidLine));
        else
 //             painter->SetPen(QPen(Qt::blue, 1.0, Qt::SolidLine));
 #endif
@@ -219,44 +219,18 @@ I believe they are pixels.
 
 /*virtual*/ void Dimension::PointerMoved(Vector point)
 {
-#if 0
-       // We know this is true because mouse move messages don't come here unless
-       // the object was actually clicked on--therefore we *know* we're being
-       // dragged...
-       objectWasDragged = true;
-
-/*     if (dragging)
-       {
-               // Here we need to check whether or not we're dragging a handle or the object itself...
-               Vector delta = point - oldPoint;
-
-               position += delta;
-               endpoint += delta;
-
-               oldPoint = point;
-               needUpdate = true;
-       }
-       else*/ if (draggingHandle1)
+       if (selectionInProgress)
        {
-               Vector delta = point - oldPoint;
-
-               position += delta;
+               // Check for whether or not the rect contains this line
+               if (selection.contains(position.x, position.y)
+                       && selection.contains(endpoint.x, endpoint.y))
+                       state = OSSelected;
+               else
+                       state = OSInactive;
 
-               oldPoint = point;
-               needUpdate = true;
+               return;
        }
-       else if (draggingHandle2)
-       {
-               Vector delta = point - oldPoint;
-
-               endpoint += delta;
 
-               oldPoint = point;
-               needUpdate = true;
-       }
-       else
-               needUpdate = false;
-#else
        // 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();
@@ -278,7 +252,6 @@ I believe they are pixels.
                oldPoint = point;
                needUpdate = true;
        }
-#endif
 }
 
 
index ca146bb4a48abd184e9343b52c58c8d3aa0e6592..a5767a3ebfb4ad94a17492788424d29838e2743c 100644 (file)
@@ -11,6 +11,7 @@ enum DimensionType { DTLinear, DTLinearVert, DTLinearHorz, DTRadial, DTDiametric
 class Dimension: public Object
 {
        friend class Line;
+       friend class Geometry;
 
        public:
                Dimension(Vector, Vector, DimensionType dt = DTLinear, Object * p = 0);
index eacaec7feabc20ee4b8cddce4a15e538f2905bd4..cfb051101c94498c1e026bacc7a2a58379d7f0ec 100644 (file)
@@ -15,8 +15,9 @@
 
 #include "geometry.h"
 #include <math.h>
-#include "line.h"
 #include "circle.h"
+#include "dimension.h"
+#include "line.h"
 
 
 Point Geometry::IntersectionOfLineAndLine(Point p1, Point p2, Point p3, Point p4)
@@ -128,18 +129,57 @@ int Geometry::Intersects(Line * l1, Line * l2, double * tp/*= 0*/, double * up/*
 {
        Vector r(l1->position, l1->endpoint);
        Vector s(l2->position, l2->endpoint);
-       Vector v1 = l2->position - l1->position;
-//     Vector v1 = l1->position - l2->position;
-
+       Vector v1 = l2->position - l1->position;        // q - p
+//     Vector v2 = l1->position - l2->position;        // p - q
+//printf("l1: (%lf, %lf) (%lf, %lf), l2: (%lf, %lf) (%lf, %lf)\n", l1->position.x, l1->position.y, l1->endpoint.x, l1->endpoint.y, l2->position.x, l2->position.y, l2->endpoint.x, l2->endpoint.y);
        double rxs = (r.x * s.y) - (s.x * r.y);
+       double t, u;
 
        if (rxs == 0)
-               return 0;
+       {
+               double qpxr = (v1.x * r.y) - (r.x * v1.y);
 
-       double t = ((v1.x * s.y) - (s.x * v1.y)) / rxs;
-       double u = ((v1.x * r.y) - (r.x * v1.y)) / rxs;
+//printf("  --> R x S = 0! (q - p) x r = %lf\n", qpxr);
+//printf("  -->(q - p) . r = %lf, r . r = %lf\n", v1.Dot(r), r.Dot(r));
+//printf("  -->(p - q) . s = %lf, s . s = %lf\n", v2.Dot(s), s.Dot(s));
+//printf("  -->(q - p) . s = %lf, (p - q) . r = %lf\n", v1.Dot(s), v2.Dot(r));
+
+               // Lines are parallel, so no intersection...
+               if (qpxr != 0)
+                       return 0;
+
+#if 0
+//this works IFF the vectors are pointing in the same direction. everything else
+//is fucked!
+               // If (q - p) . r == r . r, t = 1, u = 0
+               if (v1.Dot(r) == r.Dot(r))
+                       t = 1.0, u = 0;
+               // If (p - q) . s == s . s, t = 0, u = 1
+               else if (v2.Dot(s) == s.Dot(s))
+                       t = 0, u = 1.0;
+               else
+                       return 0;
+#else
+               // Check to see which endpoints are connected... Four possibilities:
+               if (l1->position == l2->position)
+                       t = 0, u = 0;
+               else if (l1->position == l2->endpoint)
+                       t = 0, u = 1.0;
+               else if (l1->endpoint == l2->position)
+                       t = 1.0, u = 0;
+               else if (l1->endpoint == l2->endpoint)
+                       t = 1.0, u = 1.0;
+               else
+                       return 0;
+#endif
+       }
+       else
+       {
+               t = ((v1.x * s.y) - (s.x * v1.y)) / rxs;
+               u = ((v1.x * r.y) - (r.x * v1.y)) / rxs;
+       }
 /*
-Now there are five cases:
+Now there are five cases (NOTE: only valid if vectors face the same way!):
 
 1. If r × s = 0 and (q − p) × r = 0, then the two lines are collinear. If in addition, either 0 ≤ (q − p) · r ≤ r · r or 0 ≤ (p − q) · s ≤ s · s, then the two lines are overlapping.
 
@@ -166,6 +206,14 @@ Now there are five cases:
 }
 
 
+// Finds the intersection between two lines (if any)
+int Geometry::Intersects(Line * l1, Dimension * d1, double * tp/*= 0*/, double * up/*= 0*/)
+{
+       Line l2(d1->position, d1->endpoint);
+       return Intersects(l1, &l2, tp, up);
+}
+
+
 // Finds the intesection(s) between a line and a circle (if any)
 int Geometry::Intersects(Line * l, Circle * c, double * tp/*= 0*/, double * up/*= 0*/, double * vp/*= 0*/, double * wp/*= 0*/)
 {
index 89360884d1bdc0f1259c0db2e3b59499fb8864ae..d19d48c8c1735fdd81d2f89494dff85c3abc0a95 100644 (file)
@@ -3,8 +3,9 @@
 
 #include "vector.h"
 
-class Line;
 class Circle;
+class Dimension;
+class Line;
 
 class Geometry
 {
@@ -16,6 +17,7 @@ class Geometry
                static Point RotatePointAroundPoint(Point, Point, double);
                static double Determinant(Point, Point);
                static int Intersects(Line *, Line *, double * tp = 0, double * up = 0);
+               static int Intersects(Line *, Dimension *, double * tp = 0, double * up = 0);
                static int Intersects(Line * l, Circle * c, double * tp = 0, double * up = 0, double * vp = 0, double * wp = 0);
 };