From 9590e4ed45fd4e05eccc16bd8e9d51596aea5a6d Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Wed, 5 Feb 2014 14:36:01 -0600 Subject: [PATCH] Fixed missing edge cases in line to line intersection function. --- src/applicationwindow.cpp | 37 +++++++++++++++++----- src/dimension.cpp | 47 ++++++---------------------- src/dimension.h | 1 + src/geometry.cpp | 64 ++++++++++++++++++++++++++++++++++----- src/geometry.h | 4 ++- 5 files changed, 99 insertions(+), 54 deletions(-) diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index 23629bc..effcc1e 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -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; jdocument.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); + } } } } diff --git a/src/dimension.cpp b/src/dimension.cpp index b3f1e7f..27823b3 100644 --- a/src/dimension.cpp +++ b/src/dimension.cpp @@ -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 } diff --git a/src/dimension.h b/src/dimension.h index ca146bb..a5767a3 100644 --- a/src/dimension.h +++ b/src/dimension.h @@ -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); diff --git a/src/geometry.cpp b/src/geometry.cpp index eacaec7..cfb0511 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -15,8 +15,9 @@ #include "geometry.h" #include -#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*/) { diff --git a/src/geometry.h b/src/geometry.h index 8936088..d19d48c 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -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); }; -- 2.37.2