]> Shamusworld >> Repos - architektonas/blobdiff - src/dimension.cpp
Added more visual feedback to Dimension type changing buttons.
[architektonas] / src / dimension.cpp
index 185b7e9645b360f6fef97d0cb2978eada8a45dce..8729b1cce27862a7842b1175dee87c1ec0f92fe9 100644 (file)
 // (C) 2011 Underground Software
 // See the README and GPLv3 files for licensing and warranty information
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // 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, Object * p/*= NULL*/): Object(p1, p), endpoint(p2),
+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())
+       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;
+//     dimensionType = DTLinearHorz;
 }
 
+
 Dimension::~Dimension()
 {
 }
 
-/*virtual*/ void Dimension::Draw(QPainter * painter)
+
+/*
+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)
 {
+       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+
+       if ((state == OSSelected) || ((state == OSInactive) && hitPoint1))
+               painter->DrawHandle(position);
+
+       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 ortho;
+       double x1, y1, length;
+
+       if (dimensionType == DTLinearVert)
+       {
+               if ((angle < 0) || (angle > PI))
+       //      if ((angle < PI_OVER_2) || (angle > PI3_OVER_2))
+               {
+                       x1 = (position.x > endpoint.x ? position.x : endpoint.x);
+                       y1 = (position.y > endpoint.y ? position.y : endpoint.y);
+                       ortho = Vector(1.0, 0);
+       //              ortho = Vector(0, 1.0);
+                       angle = PI3_OVER_2;
+       //              angle = 0;
+               }
+               else
+               {
+                       x1 = (position.x > endpoint.x ? endpoint.x : position.x);
+                       y1 = (position.y > endpoint.y ? endpoint.y : position.y);
+                       ortho = Vector(-1.0, 0);
+       //              ortho = Vector(0, -1.0);
+                       angle = PI_OVER_2;
+       //              angle = PI;
+               }
 
-       // Get our line parallel to our points
-       Point p1 = position + (orthogonal * 10.0);
-       Point p2 = endpoint + (orthogonal * 10.0);
+               linePt1.x = linePt2.x = x1;
+               length = fabs(position.y - endpoint.y);
+       }
+       else if (dimensionType == DTLinearHorz)
+       {
+               if ((angle < PI_OVER_2) || (angle > PI3_OVER_2))
+               {
+                       x1 = (position.x > endpoint.x ? position.x : endpoint.x);
+                       y1 = (position.y > endpoint.y ? position.y : endpoint.y);
+                       ortho = Vector(0, 1.0);
+                       angle = 0;
+               }
+               else
+               {
+                       x1 = (position.x > endpoint.x ? endpoint.x : position.x);
+                       y1 = (position.y > endpoint.y ? endpoint.y : position.y);
+                       ortho = Vector(0, -1.0);
+                       angle = PI;
+               }
+
+               linePt1.y = linePt2.y = y1;
+               length = fabs(position.x - endpoint.x);
+       }
+       else if (dimensionType == DTLinear)
+       {
+               angle = Vector(linePt1, linePt2).Angle();
+               ortho = Vector::Normal(linePt1, linePt2);
+               length = v.Magnitude();
+       }
 
-       // Draw main dimension line
-       painter->drawLine(QPointF(p1.x, p1.y), QPointF(p2.x, p2.y));
+       unit = Vector(linePt1, linePt2).Unit();
+//     angle = Vector(linePt1, linePt2).Angle();
+//     ortho = Vector::Normal(linePt1, linePt2);
 
-       Point p3 = position + (orthogonal * 16.0);
-       Point p4 = endpoint + (orthogonal * 16.0);
-       Point p5 = position + (orthogonal * 4.0);
-       Point p6 = endpoint + (orthogonal * 4.0);
+       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 * size);
+       Point p2 = endpoint + (orthogonal * 10.0 * size);
 
-       // Draw extension lines
-       painter->drawLine(QPointF(p3.x, p3.y), QPointF(p5.x, p5.y));
-       painter->drawLine(QPointF(p4.x, p4.y), QPointF(p6.x, p6.y));
+       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);
+
+       // 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));
-       Vector v1((p1.x - p2.x) / 2.0, (p1.y - p2.y) / 2.0);
-       Point ctr = p2 + v1;
+       painter->SetFont(QFont("Arial", 8.0 * Painter::zoom * size));
+       Point ctr = p2 + (Vector(p2, p1) / 2.0);
+
+#if 0
        QString dimText = QString("%1\"").arg(Vector(endpoint - position).Magnitude());
-       int textWidth = QFontMetrics(painter->font()).width(dimText);
-       int textHeight = QFontMetrics(painter->font()).height();
-//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
+       QString dimText;
+
+       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
 
-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();
+       painter->DrawAngledText(ctr, angle, dimText, size);
+
+       if (hitLine)
+       {
+               Point hp1 = (p1 + p2) / 2.0;
+               Point hp2 = (p1 + hp1) / 2.0;
+               Point hp3 = (hp1 + p2) / 2.0;
+
+               if (hitFlipSwitch)
+               {
+                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                       painter->DrawArrowHandle(hp1, ortho.Angle() + PI);
+                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+               }
+
+               painter->DrawHandle(hp1);
+               painter->SetPen(QPen(Qt::blue, 1.0 * Painter::zoom * size, Qt::SolidLine));
+
+               if (hitChangeSwitch1)
+               {
+                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                       painter->DrawArrowToLineHandle(hp2, (dimensionType == DTLinearVert ? ortho.Angle() : 0));
+                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+               }
+
+               painter->DrawHandle(hp2);
+               painter->SetPen(QPen(Qt::blue, 1.0 * Painter::zoom * size, Qt::SolidLine));
+
+               if (hitChangeSwitch2)
+               {
+                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                       painter->DrawArrowToLineHandle(hp3, PI_OVER_2);
+                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+               }
+
+               painter->DrawHandle(hp3);
+       }
 }
 
+
 /*virtual*/ Vector Dimension::Center(void)
 {
        // Technically, this is the midpoint but who are we to quibble? :-)
@@ -97,149 +253,116 @@ painter->restore();
        return endpoint + v;
 }
 
-/*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;
+       }
+       else if (hitFlipSwitch)
+       {
+               FlipSides();
+               hitFlipSwitch = hitLine = false;
+//             state = OSInactive;
+//             return true;
+       }
+       else if (hitChangeSwitch1)
+       {
+               // There are three cases here: aligned, horizontal, & vertical. Aligned
+               // and horizontal do the same thing, vertical goes back to linear.
+               if (dimensionType == DTLinearVert)
+                       dimensionType = DTLinear;
+               else
+                       dimensionType = DTLinearVert;
+
+               hitFlipSwitch = hitLine = false;
+       }
+       else if (hitChangeSwitch2)
+       {
+               // There are three cases here: aligned, horizontal, & vertical. Aligned
+               // and vertical do the same thing, horizontal goes back to linear.
+               if (dimensionType == DTLinearHorz)
+                       dimensionType = DTLinear;
+               else
+                       dimensionType = DTLinearHorz;
+
+               hitFlipSwitch = hitLine = false;
        }
-#endif
 
        state = OSInactive;
        return false;
 }
 
-/*virtual*/ void 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)
+/*virtual*/ bool Dimension::PointerMoved(Vector point)
+{
+       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)
@@ -247,23 +370,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;
@@ -279,22 +401,233 @@ about keeping track of old states...
                state = oldState;
 }
 
-void Dimension::SetPoint1(Vector v)
+
+/*virtual*/ bool Dimension::HitTest(Point point)
 {
-       position = v;
-       needUpdate = true;
+//     Vector orthogonal = Vector::Normal(position, endpoint);
+       Vector orthogonal = Vector::Normal(linePt1, linePt2);
+       // 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 = hitChangeSwitch1
+               = hitChangeSwitch2 = 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;
+       Point midpoint = (p1 + p2) / 2.0;
+       Point hFSPoint = Point(midpoint, point);
+       Point hCS1Point = Point((p1 + midpoint) / 2.0, point);
+       Point hCS2Point = Point((midpoint + p2) / 2.0, point);
+
+       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;
+
+       if ((hFSPoint.Magnitude() * Painter::zoom) < 8.0)
+               hitFlipSwitch = true;
+       else if ((hCS1Point.Magnitude() * Painter::zoom) < 8.0)
+               hitChangeSwitch1 = true;
+       else if ((hCS2Point.Magnitude() * Painter::zoom) < 8.0)
+               hitChangeSwitch2 = true;
+
+       return (hitPoint1 || hitPoint2 || hitLine || hitFlipSwitch || hitChangeSwitch1 || hitChangeSwitch2 ? true : false);
 }
 
-void Dimension::SetPoint2(Vector v)
+
+void Dimension::SaveHitState(void)
 {
-       endpoint = v;
-       needUpdate = true;
+       oldHitPoint1 = hitPoint1;
+       oldHitPoint2 = hitPoint2;
+       oldHitLine = hitLine;
+       oldHitFlipSwitch = hitFlipSwitch;
+       oldHitChangeSwitch1 = hitChangeSwitch1;
+       oldHitChangeSwitch2 = hitChangeSwitch2;
+}
+
+
+bool Dimension::HitStateChanged(void)
+{
+       if ((hitPoint1 != oldHitPoint1) || (hitPoint2 != oldHitPoint2)
+               || (hitLine != oldHitLine) || (hitFlipSwitch != oldHitFlipSwitch)
+               || (hitChangeSwitch1 != oldHitChangeSwitch1)
+               || (hitChangeSwitch2 != oldHitChangeSwitch2))
+               return true;
+
+       return 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);
+}
+
+
+/*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;
 }
 
+
+/*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
+       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;
 }
+