X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdimension.cpp;h=63e1ba2e7f50b9b38778974d467e78b5a24c56e6;hb=fd5a80446b2abfdfb9d8951fcc03fb1b55ad707c;hp=db2a2085d42bd730048aa536a3d31ffebe1320cc;hpb=c58b8a9f8b1ae5494857fc423ed8e33b2bbcf329;p=architektonas diff --git a/src/dimension.cpp b/src/dimension.cpp index db2a208..63e1ba2 100644 --- a/src/dimension.cpp +++ b/src/dimension.cpp @@ -15,6 +15,7 @@ #include "dimension.h" #include +#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);