]> Shamusworld >> Repos - architektonas/blobdiff - src/dimension.cpp
Misc. fixes & additions
[architektonas] / src / dimension.cpp
index db2a2085d42bd730048aa536a3d31ffebe1320cc..63e1ba2e7f50b9b38778974d467e78b5a24c56e6 100644 (file)
@@ -15,6 +15,7 @@
 #include "dimension.h"
 
 #include <QtGui>
+#include "geometry.h"
 #include "mathconstants.h"
 #include "painter.h"
 
@@ -43,6 +44,21 @@ Dimension::~Dimension()
 }
 
 
+/*
+The approach used below creates a hierarchy: Dimension is subservient to Line.
+
+Does this solve our problem of connected objects? Maybe, partially. Let's think this
+through. It only works for endpoints, not points in the middle...
+
+Also: this is bad, depending on the Draw() function to update the internal
+      position(s) of the data of the object! (is it though?)
+
+How to move: click once moves only the object/point clicked on, all connected
+objects deform themselves accordingly. click twice selects ALL connected objects;
+all objects move as a unified whole.
+
+*/
+
 /*virtual*/ void Dimension::Draw(Painter * painter)
 {
        // If there are valid Vector pointers in here, use them to update the internal
@@ -93,8 +109,7 @@ I believe they are pixels.
        // Calculate whether or not the arrowheads are too crowded to put inside
        // the extension lines. 9.0 is the length of the arrowhead.
 //     double t = Vector::Parameter(position, endpoint, endpoint - (unit * 9.0 * size));
-       double t = Vector::Parameter(position, endpoint, position + (unit * 9.0 * size));
-//     double t = Vector::Parameter(endpoint, position, position + (unit * 9.0 * size));
+       double t = Geometry::ParameterOfLineAndPoint(position, endpoint, endpoint - (unit * 9.0 * size));
 //printf("Dimension::Draw(): t = %lf\n", t);
 
 // On the screen, it's acting like this is actually 58%...
@@ -154,101 +169,37 @@ I believe they are pixels.
 }
 
 
-/*virtual*/ bool Dimension::Collided(Vector /*point*/)
+/*virtual*/ bool Dimension::Collided(Vector point)
 {
-#if 0
+       // 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;
-       Vector lineSegment = endpoint - position;
-       Vector v1 = point - position;
-       Vector v2 = point - endpoint;
-       double parameterizedPoint = lineSegment.Dot(v1) / lineSegment.Magnitude(), distance;
-
-       // Geometric interpretation:
-       // pp is the paremeterized point on the vector ls where the perpendicular intersects ls.
-       // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,
-       // then the perpendicular lies beyond the 2nd endpoint.
-
-       if (parameterizedPoint < 0.0)
-               distance = v1.Magnitude();
-       else if (parameterizedPoint > lineSegment.Magnitude())
-               distance = v2.Magnitude();
-       else                                    // distance = ?Det?(ls, v1) / |ls|
-               distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y) / lineSegment.Magnitude());
-
-       // If the segment endpoints are s and e, and the point is p, then the test for the perpendicular
-       // intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and
-       // {e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is
-       // computed by first computing the area of the triangle the three points form, then dividing by the
-       // length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the
-       // triangle formed by three points is the determinant of the following matrix:
-       //
-       // sx sy 1
-       // ex ey 1
-       // px py 1
-       //
-       // By translating the start point to the origin, this can be rewritten as:
-       // By subtracting row 1 from all rows, you get the following:
-       // [because sx = sy = 0. you could leave out the -sx/y terms below. because we subtracted
-       // row 1 from all rows (including row 1) row 1 turns out to be zero. duh!]
-       //
-       // 0         0         0        0  0  0
-       // (ex - sx) (ey - sy) 0   ==>  ex ey 0
-       // (px - sx) (py - sy) 0        px py 0
-       //
-       // which greatly simplifies the calculation of the determinant.
-
-       if (state == OSInactive)
+       HitTest(point);
+
+       // Now that we've done our hit testing on the non-snapped point, snap it if
+       // necessary...
+       if (snapToGrid)
+               point = SnapPointToGrid(point);
+
+       if (hitPoint1)
        {
-//printf("Line: pp = %lf, length = %lf, distance = %lf\n", parameterizedPoint, lineSegment.Magnitude(), distance);
-//printf("      v1.Magnitude = %lf, v2.Magnitude = %lf\n", v1.Magnitude(), v2.Magnitude());
-//printf("      point = %lf,%lf,%lf; p1 = %lf,%lf,%lf; p2 = %lf,%lf,%lf\n", point.x, point.y, point.z, position.x, position.y, position.z, endpoint.x, endpoint.y, endpoint.z);
-//printf("      \n", );
-//How to translate this into pixels from Document space???
-//Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
-//the caller knows about the zoom factor and all that good kinda crap
-               if (v1.Magnitude() < 10.0)
-               {
-                       oldState = state;
-                       state = OSSelected;
-                       oldPoint = position; //maybe "position"?
-                       draggingHandle1 = true;
-                       return true;
-               }
-               else if (v2.Magnitude() < 10.0)
-               {
-                       oldState = state;
-                       state = OSSelected;
-                       oldPoint = endpoint; //maybe "position"?
-                       draggingHandle2 = true;
-                       return true;
-               }
-               else if (distance < 2.0)
-               {
-                       oldState = state;
-                       state = OSSelected;
-                       oldPoint = point;
-                       dragging = true;
-                       return true;
-               }
+//             oldState = state;
+//             state = OSSelected;
+               oldPoint = position;
+               draggingHandle1 = true;
+               return true;
        }
-       else if (state == OSSelected)
+       else if (hitPoint2)
        {
-               // Here we test for collision with handles as well! (SOON!)
-/*
-Like so:
-               if (v1.Magnitude() < 2.0) // Handle #1
-               else if (v2.Magnitude() < 2.0) // Handle #2
-*/
-               if (distance < 2.0)
-               {
-                       oldState = state;
-//                     state = OSInactive;
-                       oldPoint = point;
-                       dragging = true;
-                       return true;
-               }
+//             oldState = state;
+//             state = OSSelected;
+               oldPoint = endpoint;
+               draggingHandle2 = true;
+               return true;
        }
-#endif
 
        state = OSInactive;
        return false;
@@ -262,7 +213,7 @@ Like so:
        // dragged...
        objectWasDragged = true;
 
-       if (dragging)
+/*     if (dragging)
        {
                // Here we need to check whether or not we're dragging a handle or the object itself...
                Vector delta = point - oldPoint;
@@ -273,7 +224,7 @@ Like so:
                oldPoint = point;
                needUpdate = true;
        }
-       else if (draggingHandle1)
+       else*/ if (draggingHandle1)
        {
                Vector delta = point - oldPoint;
 
@@ -298,7 +249,7 @@ Like so:
 
 /*virtual*/ void Dimension::PointerReleased(void)
 {
-       if (draggingHandle1 || draggingHandle2)
+/*     if (draggingHandle1 || draggingHandle2)
        {
                // Set the length (in case the global state was set to fixed (or not))
                if (Object::fixedLength)
@@ -306,23 +257,22 @@ Like so:
 
                        if (draggingHandle1)    // startpoint
                        {
-                               Vector v = Vector(position - endpoint).Unit() * length;
+                               Vector v = Vector(endpoint, position).Unit() * length;
                                position = endpoint + v;
                        }
                        else                                    // endpoint
                        {
-//                             Vector v1 = endpoint - position;
-                               Vector v = Vector(endpoint - position).Unit() * length;
+                               Vector v = Vector(position, endpoint).Unit() * length;
                                endpoint = position + v;
                        }
                }
-               else
+               else*/
                {
                        // Otherwise, we calculate the new length, just in case on the next move
                        // it turns out to have a fixed length. :-)
                        length = Vector(endpoint - position).Magnitude();
                }
-       }
+/*     }*/
 
        dragging = false;
        draggingHandle1 = false;
@@ -339,6 +289,33 @@ about keeping track of old states...
 }
 
 
+/*virtual*/ bool Dimension::HitTest(Point point)
+{
+       hitPoint1 = hitPoint2 = false;
+//     Vector lineSegment(position, endpoint);
+       Vector v1(position, point);
+       Vector v2(endpoint, point);
+//     double t = Geometry::ParameterOfLineAndPoint(position, endpoint, point);
+//     double distance;
+
+//     if (t < 0.0)
+//             distance = v1.Magnitude();
+//     else if (t > 1.0)
+//             distance = v2.Magnitude();
+//     else
+               // distance = ?Det?(ls, v1) / |ls|
+//             distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y)
+//                     / lineSegment.Magnitude());
+
+       if ((v1.Magnitude() * Painter::zoom) < 8.0)
+               hitPoint1 = true;
+       else if ((v2.Magnitude() * Painter::zoom) < 8.0)
+               hitPoint2 = true;
+
+       return (hitPoint1 || hitPoint2 ? true : false);
+}
+
+
 /*virtual*/ void Dimension::Enumerate(FILE * file)
 {
        fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, type);