]> Shamusworld >> Repos - architektonas/blobdiff - src/dimension.cpp
Trim tool now works for Lines, but inaccurate.
[architektonas] / src / dimension.cpp
index ad2ffcbe38a08bd88fbbc85ea8333060306862d1..675afaff89c7c7a3cef7e4f98df0233a51fcaa91 100644 (file)
 // WHO  WHEN        WHAT
 // ---  ----------  ------------------------------------------------------------
 // JLH  04/04/2011  Created this file, basic rendering
+// JLH  03/14/2013  Updated to new connection system
 //
 
 #include "dimension.h"
 
 #include <QtGui>
+#include "geometry.h"
 #include "mathconstants.h"
 #include "painter.h"
 
 
-Dimension::Dimension(Vector p1, Vector p2, DimensionType dt/*= DTLinear*/ ,Object * p/*= NULL*/):
+Dimension::Dimension(Vector p1, Vector p2, DimensionType dt/*= DTLinear*/Object * p/*= NULL*/):
        Object(p1, p), endpoint(p2),
        dragging(false), draggingHandle1(false), draggingHandle2(false),
-       length(p2.Magnitude()), type(dt), point1(NULL), point2(NULL)
+       length(p2.Magnitude()), dimensionType(dt), size(0.25)//, point1(NULL), point2(NULL)
 {
+       // We set the size to 1/4 base unit. Could be anything.
+       type = OTDimension;
 }
 
-
+#if 0
 // This is bad, p1 & p2 could be NULL, causing much consternation...
-Dimension::Dimension(Vector * p1, Vector * p2, DimensionType dt/*= DTLinear*/ , Object * p/*= NULL*/):
-       Object(*p1, p), endpoint(*p2),
+Dimension::Dimension(Connection p1, Connection p2, DimensionType dt/*= DTLinear*/, Object * p/*= NULL*/):
        dragging(false), draggingHandle1(false), draggingHandle2(false),
-       length(p2->Magnitude()), type(dt), point1(p1), point2(p2)
+       length(0), dimensionType(dt), size(0.25)//, point1(p1), point2(p2)
 {
+       type = OTDimension;
 }
-
+#endif
 
 Dimension::~Dimension()
 {
 }
 
 
+/*
+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
-       // positions. Otherwise, we just use the internal positions by default.
-       if (point1)
-               position = *point1;
+       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+
+       if ((state == OSSelected) || ((state == OSInactive) && hitPoint1))
+               painter->DrawHandle(position);
 
-       if (point2)
-               endpoint = *point2;
+       if ((state == OSSelected) || ((state == OSInactive) && hitPoint2))
+               painter->DrawHandle(endpoint);
 
        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));
+               painter->SetPen(QPen(Qt::blue, 1.0 * Painter::zoom * size, Qt::SolidLine));
+
+       painter->SetBrush(QBrush(QColor(Qt::blue)));
 
        // Draw an aligned dimension line
-       double angle = Vector(endpoint - position).Angle();
-       double orthoAngle = angle + (PI / 2.0);
-       Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
-       Vector unit = Vector(endpoint - position).Unit();
+       Vector v(position, endpoint);
+       double angle = v.Angle();
+       Vector orthogonal = Vector::Normal(position, endpoint);
+       Vector unit = v.Unit();
+       linePt1 = position, linePt2 = endpoint;
+
+// Horizontally aligned display
+#if 1
+       Vector /*pos = position, endp = endpoint,*/ ortho;
+       double y1;
+
+       if ((angle < PI_OVER_2) || (angle > PI3_OVER_2))
+       {
+               y1 = (position.y > endpoint.y ? position.y : endpoint.y);
+               ortho = Vector(0, 1.0);
+               angle = 0;
+       }
+       else
+       {
+               y1 = (position.y > endpoint.y ? endpoint.y : position.y);
+               ortho = Vector(0, -1.0);
+               angle = PI;
+       }
 
-//NOTE: SCREEN_ZOOM is our kludge factor... We need to figure out a better
-//      way of doing this...
+//     pos.y = endp.y = y1;
+       linePt1.y = linePt2.y = y1;
+       unit = Vector(linePt1, linePt2).Unit();
+       Point p1 = linePt1 + (ortho * 10.0 * size);
+       Point p2 = linePt2 + (ortho * 10.0 * size);
+       Point p3 = linePt1 + (ortho * 16.0 * size);
+       Point p4 = linePt2 + (ortho * 16.0 * size);
+       Point p5 = position + (ortho * 4.0 * size);
+       Point p6 = endpoint + (ortho * 4.0 * size);
+#endif
+/*
+The numbers hardcoded into here, what are they?
+I believe they are pixels.
+*/
+#if 0
        // Get our line parallel to our points
-       Point p1 = position + (orthogonal * 10.0 * SCREEN_ZOOM);
-       Point p2 = endpoint + (orthogonal * 10.0 * SCREEN_ZOOM);
-
-       // Draw main dimension line
-       painter->DrawLine(p1, p2);
+       Point p1 = position + (orthogonal * 10.0 * size);
+       Point p2 = endpoint + (orthogonal * 10.0 * size);
 
-       Point p3 = position + (orthogonal * 16.0 * SCREEN_ZOOM);
-       Point p4 = endpoint + (orthogonal * 16.0 * SCREEN_ZOOM);
-       Point p5 = position + (orthogonal * 4.0 * SCREEN_ZOOM);
-       Point p6 = endpoint + (orthogonal * 4.0 * SCREEN_ZOOM);
-
-       // Draw extension lines
+       Point p3 = position + (orthogonal * 16.0 * size);
+       Point p4 = endpoint + (orthogonal * 16.0 * size);
+       Point p5 = position + (orthogonal * 4.0 * size);
+       Point p6 = endpoint + (orthogonal * 4.0 * size);
+#endif
+       // Draw extension lines (if certain type)
        painter->DrawLine(p3, p5);
        painter->DrawLine(p4, p6);
 
-       painter->SetBrush(QBrush(QColor(Qt::blue)));
-       painter->DrawArrowhead(p1, p2);
-       painter->DrawArrowhead(p2, p1);
+       // 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 = Geometry::ParameterOfLineAndPoint(position, endpoint, endpoint - (unit * 9.0 * size));
+//     double t = Geometry::ParameterOfLineAndPoint(pos, endp, endp - (unit * 9.0 * size));
+       double t = Geometry::ParameterOfLineAndPoint(linePt1, linePt2, linePt2 - (unit * 9.0 * size));
+//printf("Dimension::Draw(): t = %lf\n", t);
+
+// On the screen, it's acting like this is actually 58%...
+// This is correct, we want it to happen at > 50%
+       if (t > 0.58)
+       {
+               // Draw main dimension line + arrowheads
+               painter->DrawLine(p1, p2);
+               painter->DrawArrowhead(p1, p2, size);
+               painter->DrawArrowhead(p2, p1, size);
+       }
+       else
+       {
+               // Draw outside arrowheads
+               Point p7 = p1 - (unit * 9.0 * size);
+               Point p8 = p2 + (unit * 9.0 * size);
+               painter->DrawArrowhead(p1, p7, size);
+               painter->DrawArrowhead(p2, p8, size);
+               painter->DrawLine(p1, p1 - (unit * 14.0 * size));
+               painter->DrawLine(p2, p2 + (unit * 14.0 * size));
+       }
 
        // Draw length of dimension line...
-       painter->SetFont(QFont("Arial", 10.0 * Painter::zoom * SCREEN_ZOOM));
+       painter->SetFont(QFont("Arial", 8.0 * Painter::zoom * size));
+#if 0
        Vector v1((p1.x - p2.x) / 2.0, (p1.y - p2.y) / 2.0);
        Point ctr = p2 + v1;
-       // This is in pixels, which isn't even remotely correct... !!! FIX !!!
-       QString dimText = QString("%1\"").arg(Vector(endpoint - position).Magnitude());
-//     int textWidth = QFontMetrics(painter->font()).width(dimText);
-//     int textHeight = QFontMetrics(painter->font()).height();
-#if 0
-//We have to do transformation voodoo to make the text come out readable and in correct orientation...
-//Some things to note here: if angle > 90 degrees, then we need to take the negative of the angle
-//for our text.
-painter->save();
-painter->translate(ctr.x, ctr.y);
-int yOffset = -8;
-//16 : printf("textHeight: %d\n", textHeight);
-
-//Fix text so it isn't upside down...
-if ((angle > PI * 0.5) && (angle < PI * 1.5))
-{
-       angle += PI;
-       yOffset = 18;
-}
+#else
+       Point ctr = p2 + (Vector(p2, p1) / 2.0);
+#endif
 
-painter->rotate(angle * RADIANS_TO_DEGREES);
-painter->scale(1.0, -1.0);
-//painter->translate(-textWidth / 2, -24);
-//     painter->drawText(0, 0, textWidth, 20, Qt::AlignCenter, dimText);
-       // This version draws the y-coord from the baseline of the font
-       painter->DrawText(-textWidth / 2, yOffset, dimText);
-//painter->setPen(QPen(QColor(0xFF, 0x20, 0x20), 1.0, Qt::SolidLine));
-//painter->drawLine(20, 0, -20, 0);
-//painter->drawLine(0, 20, 0, -20);
-painter->restore();
+#if 0
+       QString dimText = QString("%1\"").arg(Vector(endpoint - position).Magnitude());
 #else
-//     painter->DrawText(QRectF(QPointF(ctr.x, ctr.y), QPointF(ctr.x + textWidth, ctr.y + textHeight)), Qt::AlignVCenter, dimText);
-// Now that we've taken our own good advice, maybe we should have the painter class
-// do a nice abstracted text draw routine? :-)
-       painter->DrawAngledText(ctr, angle, dimText);
+       QString dimText;
+//     double length = v.Magnitude();
+       double length = fabs(position.x - endpoint.x);
+
+       if (length < 12.0)
+               dimText = QString("%1\"").arg(length);
+       else
+       {
+               double feet = (double)((int)length / 12);
+               double inches = length - (feet * 12.0);
+
+               if (inches == 0)
+                       dimText = QString("%1'").arg(feet);
+               else
+                       dimText = QString("%1' %2\"").arg(feet).arg(inches);
+       }
 #endif
 
-/*
-All of the preceeding makes me think that rather than try to compensate for Qt's unbelieveably
-AWFUL decision to go with a wrong-handed graphics subsystem, it may be better to just stuff
-all of that crap into some kind of subclass that handles all the nastiness behind the scenes.
-I mean, really, all this crap just to get some proplerly rendered text on the screen? How
-retarded is that? :-/
-*/
+       painter->DrawAngledText(ctr, angle, dimText, size);
+
+// need to make another handle drawing function in Painter, instead of this
+       if (hitLine)
+       {
+               Point p9 = ((position + endpoint) / 2.0) + (orthogonal * 14.0)
+                + (unit * 7.0);
+
+               Point p10 = p9 + (orthogonal * -7.0);
+               Point p11 = p10 + (unit * 7.0);
+               Point p12 = p11 + (orthogonal * 7.0);
+               Point p13 = p12 + (unit * -7.0);
+               painter->DrawLine(p10, p11);
+               painter->DrawLine(p11, p12);
+               painter->DrawLine(p12, p13);
+               painter->DrawLine(p13, p10);
+       }
 }
 
 
@@ -142,151 +206,86 @@ retarded is that? :-/
 }
 
 
-/*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;
+       HitTest(point);
 
-       // 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.
+       // Now that we've done our hit testing on the non-snapped point, snap it if
+       // necessary...
+       if (snapToGrid)
+               point = SnapPointToGrid(point);
 
-       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)
+       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;
 }
 
 
-/*virtual*/ void Dimension::PointerMoved(Vector point)
+/*virtual*/ bool Dimension::PointerMoved(Vector point)
 {
-       // 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)
+       if (selectionInProgress)
        {
-               // 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;
+               // 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 false;
        }
-       else if (draggingHandle1)
-       {
-               Vector delta = point - oldPoint;
 
-               position += delta;
+       // 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();
+       bool hovered = HitTest(point);
+       needUpdate = HitStateChanged();
 
-               oldPoint = point;
-               needUpdate = true;
-       }
-       else if (draggingHandle2)
+       objectWasDragged = (/*draggingLine |*/ draggingHandle1 | draggingHandle2);
+
+       if (objectWasDragged)
        {
                Vector delta = point - oldPoint;
 
-               endpoint += delta;
+               if (draggingHandle1)// || draggingLine)
+                       position += delta;
+
+               if (draggingHandle2)// || draggingLine)
+                       endpoint += delta;
 
                oldPoint = point;
                needUpdate = true;
        }
-       else
-               needUpdate = false;
+
+       return hovered;
 }
 
 
 /*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)
@@ -294,23 +293,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;
@@ -327,49 +325,213 @@ about keeping track of old states...
 }
 
 
-void Dimension::SetPoint1(Vector * v)
+/*virtual*/ bool Dimension::HitTest(Point point)
 {
-       point1 = v;
-       needUpdate = true;
+       Vector orthogonal = Vector::Normal(position, endpoint);
+       // Get our line parallel to our points
+#if 0
+       Point p1 = position + (orthogonal * 10.0 * size);
+       Point p2 = endpoint + (orthogonal * 10.0 * size);
+#else
+       Point p1 = linePt1 + (orthogonal * 10.0 * size);
+       Point p2 = linePt2 + (orthogonal * 10.0 * size);
+#endif
+       Point p3(p1, point);
+
+       hitPoint1 = hitPoint2 = hitLine = hitFlipSwitch = false;
+       Vector v1(position, point);
+       Vector v2(endpoint, point);
+//     Vector lineSegment(position, endpoint);
+       Vector lineSegment(p1, p2);
+//     double t = Geometry::ParameterOfLineAndPoint(position, endpoint, point);
+       double t = Geometry::ParameterOfLineAndPoint(p1, p2, 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)
+               distance = fabs((lineSegment.x * p3.y - p3.x * lineSegment.y)
+                       / lineSegment.Magnitude());
+
+       if ((v1.Magnitude() * Painter::zoom) < 8.0)
+               hitPoint1 = true;
+       else if ((v2.Magnitude() * Painter::zoom) < 8.0)
+               hitPoint2 = true;
+       else if ((distance * Painter::zoom) < 5.0)
+               hitLine = true;
+
+       return (hitPoint1 || hitPoint2 || hitLine ? true : false);
 }
 
 
-void Dimension::SetPoint2(Vector * v)
+void Dimension::SaveHitState(void)
 {
-       point2 = v;
-       needUpdate = true;
+       oldHitPoint1 = hitPoint1;
+       oldHitPoint2 = hitPoint2;
+       oldHitLine = hitLine;
+}
+
+
+bool Dimension::HitStateChanged(void)
+{
+       if ((hitPoint1 != oldHitPoint1) || (hitPoint2 != oldHitPoint2) || (hitLine != oldHitLine))
+               return true;
+
+       return false;
 }
 
 
-Vector Dimension::GetPoint1(void)
+/*virtual*/ void Dimension::Enumerate(FILE * file)
 {
-       return position;
+       fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, type);
 }
 
 
-Vector Dimension::GetPoint2(void)
+/*virtual*/ Object * Dimension::Copy(void)
 {
+#warning "!!! This doesn't take care of attached Dimensions !!!"
+/*
+This is a real problem. While having a pointer in the Dimension to this line's points
+is fast & easy, it creates a huge problem when trying to replicate an object like this.
+
+Maybe a way to fix that then, is to have reference numbers instead of pointers. That
+way, if you copy them, ... you might still have problems. Because you can't be sure if
+a copy will be persistant or not, you then *definitely* do not want them to have the
+same reference number.
+*/
+
+       Dimension * d = new Dimension(position, endpoint, dimensionType, parent);
+       d->size = size;
+       return d;
+}
+
+
+// Dimensions are special: they contain exactly *two* points. Here, we check
+// only for zero/non-zero in returning the correct points.
+/*virtual*/ Vector Dimension::GetPointAtParameter(double parameter)
+{
+       if (parameter == 0)
+               return position;
+
        return endpoint;
 }
 
 
-void Dimension::FlipSides(void)
+/*virtual*/ void Dimension::MovePointAtParameter(double parameter, Vector v)
+{
+       if (parameter == 0)
+               position += v;
+       else if (parameter == 1.0)
+               endpoint += v;
+       else
+               {} // Not sure how to handle this case :-P
+}
+
+#if 0
+/*virtual*/ void Dimension::Connect(Object * obj, double param)
+{
+       // There are four possibilities here...
+       // The param is only looking for 0 or 1 here.
+       if (point1.object == NULL && point2.object == NULL)
+       {
+               point1.object = obj;
+               point1.t = param;
+       }
+       else if (point1.object == NULL && point2.object != NULL)
+       {
+               if (point2.t == param)
+                       point2.object = obj;
+               else
+               {
+                       point1.object = obj;
+                       point1.t = param;
+               }
+       }
+       else if (point1.object != NULL && point2.object == NULL)
+       {
+               if (point1.t == param)
+                       point1.object = obj;
+               else
+               {
+                       point2.object = obj;
+                       point2.t = param;
+               }
+       }
+       else if (point1.object != NULL && point2.object != NULL)
+       {
+               if (point1.t == param)
+                       point1.object = obj;
+               else
+                       point2.object = obj;
+       }
+}
+
+
+/*virtual*/ void Dimension::Disconnect(Object * obj, double param)
+{
+       if (point1.object == obj && point1.t == param)
+               point1.object = NULL;
+       else if (point2.object == obj && point2.t == param)
+               point2.object = NULL;
+}
+
+
+/*virtual*/ void Dimension::DisconnectAll(Object * obj)
 {
+       if (point1.object == obj)
+               point1.object = NULL;
+
+       if (point2.object == obj)
+               point2.object = NULL;
+}
+#endif
+
+/*virtual*/ QRectF Dimension::Extents(void)
+{
+       Point p1 = position;
+       Point p2 = endpoint;
+
+//     if (point1.object)
+//             p1 = point1.object->GetPointAtParameter(point1.t);
+//
+//     if (point2.object)
+//             p2 = point2.object->GetPointAtParameter(point2.t);
+
+       return QRectF(QPointF(p1.x, p1.y), QPointF(p2.x, p2.y));
+}
+
+
 #if 0
+/*virtual*/ ObjectType Dimension::Type(void)
+{
+       return OTDimension;
+}
+#endif
+
+
+void Dimension::FlipSides(void)
+{
+#if 1
        Vector tmp = position;
        position = endpoint;
        endpoint = tmp;
+//Not sure this matters...
+//#warning "!!! May need to swap parameter values on connected objects !!!"
 #else
-       Vector * tmp = point1;
+       Connection tmp = point1;
        point1 = point2;
        point2 = tmp;
+//     double tmp = point1.t;
+//     point1.t = point2.t;
+//     point2.t = tmp;
+//     Object * tmp = point1.object;
+//     point1.object = point2.object;
+//     point2.object = tmp;
 #endif
        needUpdate = true;
 }
 
-
-/*virtual*/ void Dimension::Enumerate(FILE * file)
-{
-       fprintf(file, "DIMENSION (%lf,%lf) (%lf,%lf) %i\n", position.x, position.y, endpoint.x, endpoint.y, type);
-}
-