X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdimension.cpp;h=9c9e15c8dd5af0ed3824c7926775caab700c8ec8;hb=57056be35f9295400dd873a17d8468b3287ebc0c;hp=63e1ba2e7f50b9b38778974d467e78b5a24c56e6;hpb=fd5a80446b2abfdfb9d8951fcc03fb1b55ad707c;p=architektonas diff --git a/src/dimension.cpp b/src/dimension.cpp index 63e1ba2..9c9e15c 100644 --- a/src/dimension.cpp +++ b/src/dimension.cpp @@ -20,22 +20,14 @@ #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()), dimensionType(dt), size(0.25), 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; -} - - -// This is bad, p1 & p2 could be NULL, causing much consternation... -Dimension::Dimension(Connection p1, Connection p2, DimensionType dt/*= DTLinear*/ , Object * p/*= NULL*/): - dragging(false), draggingHandle1(false), draggingHandle2(false), - length(0), dimensionType(dt), size(0.25), point1(p1), point2(p2) -{ - type = OTDimension; +// dimensionType = DTLinearHorz; } @@ -45,14 +37,6 @@ 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. @@ -61,38 +45,101 @@ 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.object) - position = point1.object->GetPointAtParameter(point1.t); + painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine)); - if (point2.object) - endpoint = point2.object->GetPointAtParameter(point2.t); + 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; + } -// Arrowhead: -// Point p1 = head - (unit * 9.0 * size); -// Point p2 = p1 + (orthogonal * 3.0 * size); -// Point p3 = p1 - (orthogonal * 3.0 * size); + 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(); + } + + unit = Vector(linePt1, linePt2).Unit(); +// angle = Vector(linePt1, linePt2).Angle(); +// ortho = Vector::Normal(linePt1, linePt2); + + 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); @@ -101,15 +148,16 @@ I believe they are pixels. Point p4 = endpoint + (orthogonal * 16.0 * size); Point p5 = position + (orthogonal * 4.0 * size); Point p6 = endpoint + (orthogonal * 4.0 * size); - - // Draw extension lines +#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 = Vector::Parameter(position, endpoint, endpoint - (unit * 9.0 * size)); - double t = Geometry::ParameterOfLineAndPoint(position, endpoint, endpoint - (unit * 9.0 * size)); +// 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%... @@ -134,14 +182,12 @@ I believe they are pixels. // Draw length of dimension line... painter->SetFont(QFont("Arial", 8.0 * Painter::zoom * size)); - Vector v1((p1.x - p2.x) / 2.0, (p1.y - p2.y) / 2.0); - Point ctr = p2 + v1; + Point ctr = p2 + (Vector(p2, p1) / 2.0); #if 0 QString dimText = QString("%1\"").arg(Vector(endpoint - position).Magnitude()); #else QString dimText; - double length = Vector(endpoint - position).Magnitude(); if (length < 12.0) dimText = QString("%1\"").arg(length); @@ -158,6 +204,21 @@ I believe they are pixels. #endif painter->DrawAngledText(ctr, angle, dimText, size); + + if (hitLine) + { + Point hp1 = (p1 + 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); + } } @@ -186,64 +247,70 @@ I believe they are pixels. if (hitPoint1) { -// oldState = state; -// state = OSSelected; + oldState = state; + state = OSSelected; oldPoint = position; draggingHandle1 = true; return true; } else if (hitPoint2) { -// oldState = state; -// state = OSSelected; + oldState = state; + state = OSSelected; oldPoint = endpoint; draggingHandle2 = true; return true; } + else if (hitFlipSwitch) + { + FlipSides(); + hitFlipSwitch = hitLine = false; +// state = OSInactive; +// return true; + } 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; } @@ -291,28 +358,67 @@ about keeping track of old states... /*virtual*/ bool Dimension::HitTest(Point point) { - hitPoint1 = hitPoint2 = false; -// Vector lineSegment(position, endpoint); +// 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 = 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 distance; - -// if (t < 0.0) -// distance = v1.Magnitude(); -// else if (t > 1.0) -// distance = v2.Magnitude(); -// else + double t = Geometry::ParameterOfLineAndPoint(p1, p2, point); + double distance; + Point hFSPoint = Point((p1 + 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) -// / lineSegment.Magnitude()); + 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 ? true : false); + if ((hFSPoint.Magnitude() * Painter::zoom) < 8.0) + hitFlipSwitch = true; + + return (hitPoint1 || hitPoint2 || hitLine || hitFlipSwitch ? true : false); +} + + +void Dimension::SaveHitState(void) +{ + oldHitPoint1 = hitPoint1; + oldHitPoint2 = hitPoint2; + oldHitLine = hitLine; + oldHitFlipSwitch = hitFlipSwitch; +} + + +bool Dimension::HitStateChanged(void) +{ + if ((hitPoint1 != oldHitPoint1) || (hitPoint2 != oldHitPoint2) || (hitLine != oldHitLine) || (hitFlipSwitch != oldHitFlipSwitch)) + return true; + + return false; } @@ -352,6 +458,17 @@ same reference number. } +/*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... @@ -408,18 +525,18 @@ same reference number. 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); +// 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)); } @@ -435,10 +552,12 @@ same reference number. void Dimension::FlipSides(void) { -#if 0 +#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;