]> Shamusworld >> Repos - architektonas/commitdiff
Added ability to edit grid unit in base units, work on Dimension.
authorShamus Hammons <jlhamm@acm.org>
Mon, 5 Aug 2013 00:54:44 +0000 (19:54 -0500)
committerShamus Hammons <jlhamm@acm.org>
Mon, 5 Aug 2013 00:54:44 +0000 (19:54 -0500)
Basically, the Dimension object now has a thickness based on its size.
Also, it will correctly move the arrowheads to outside of the extension
lines if there is not enough room to draw them. Added Parameter() class
method to Vector to facilitate this. :-)

src/applicationwindow.cpp
src/applicationwindow.h
src/dimension.cpp
src/drawingview.cpp
src/painter.cpp
src/vector.cpp
src/vector.h

index 03f8cb5b167ef94c60c0c18d0b786032beb3e898..96b13ca8b6a66964d8094784d17f062d96342ab2 100644 (file)
@@ -469,6 +469,22 @@ void ApplicationWindow::HandleGridSizeInPixels(int size)
 }
 
 
+void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
+{
+       // Parse the text...
+       bool ok;
+       double value = text.toDouble(&ok);
+
+       // Nothing parsable to a double, so quit...
+       if (!ok)
+               return;
+
+       drawing->gridSpacing = value;
+       Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
+       drawing->update();
+}
+
+
 void ApplicationWindow::CreateActions(void)
 {
        exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
@@ -630,8 +646,11 @@ void ApplicationWindow::CreateToolbars(void)
        toolbar->setObjectName("View");
        toolbar->addAction(zoomInAct);
        toolbar->addAction(zoomOutAct);
+
        QSpinBox * spinbox = new QSpinBox;
        toolbar->addWidget(spinbox);
+       QLineEdit * lineedit = new QLineEdit;
+       toolbar->addWidget(lineedit);
 
        toolbar = addToolBar(tr("Edit"));
        toolbar->setObjectName("Edit");
@@ -650,7 +669,9 @@ void ApplicationWindow::CreateToolbars(void)
 
        spinbox->setRange(4, 256);
        spinbox->setValue(12);
+       lineedit->setText("12");
        connect(spinbox, SIGNAL(valueChanged(int)), this, SLOT(HandleGridSizeInPixels(int)));
+       connect(lineedit, SIGNAL(textChanged(QString)), this, SLOT(HandleGridSizeInBaseUnits(QString)));
 }
 
 
index 89fb9aa3e6edf703c61b776ad794869f965cc0ff..f20cd358fc1bf36f59b50033921f6e799886220e 100644 (file)
@@ -43,6 +43,7 @@ class ApplicationWindow: public QMainWindow
                void Settings(void);
                void HandleGrouping(void);
                void HandleGridSizeInPixels(int);
+               void HandleGridSizeInBaseUnits(QString);
 
        private:
                void ClearUIToolStatesExcept(QAction *);
index 8b930f05230af7b112af9a4a3e0143f8ab4860b6..203e26ffead1dddb6400d67672fd4d29855f3395 100644 (file)
@@ -56,7 +56,10 @@ Dimension::~Dimension()
        if (state == OSSelected)
                painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
        else
-               painter->SetPen(QPen(Qt::blue, 1.0, Qt::SolidLine));
+//             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();
@@ -64,21 +67,11 @@ Dimension::~Dimension()
        Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
        Vector unit = Vector(endpoint - position).Unit();
 
-#if 0
-//NOTE: SCREEN_ZOOM is our kludge factor... We need to figure out a better
-//      way of doing this...
-       // 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);
+// Arrowhead:
+//     Point p1 = head - (unit * 9.0 * size);
+//     Point p2 = p1 + (orthogonal * 3.0 * size);
+//     Point p3 = p1 - (orthogonal * 3.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);
-#else
 /*
 The numbers hardcoded into here, what are they?
 I believe they are pixels.
@@ -88,32 +81,42 @@ I believe they are pixels.
        Point p1 = position + (orthogonal * 10.0 * size);
        Point p2 = endpoint + (orthogonal * 10.0 * size);
 
-       // Draw main dimension line
-       painter->DrawLine(p1, p2);
-
        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
        painter->DrawLine(p3, p5);
        painter->DrawLine(p4, p6);
 
-       painter->SetBrush(QBrush(QColor(Qt::blue)));
-//     painter->DrawArrowhead(p1, p2);
-//     painter->DrawArrowhead(p2, p1);
-       painter->DrawArrowhead(p1, p2, size);
-       painter->DrawArrowhead(p2, p1, size);
+       // 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));
+//printf("Dimension::Draw(): t = %lf\n", t);
+
+       if (t > 0.5)
+       {
+               // Draw main dimension line + arrowheads
+               painter->DrawLine(p1, p2);
+               painter->DrawArrowhead(p1, p2, size);
+               painter->DrawArrowhead(p2, p1, size);
+       }
+       else
+       {
+               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", 10.0 * Painter::zoom * size));
        Vector v1((p1.x - p2.x) / 2.0, (p1.y - p2.y) / 2.0);
        Point ctr = p2 + v1;
        QString dimText = QString("%1\"").arg(Vector(endpoint - position).Magnitude());
-//     painter->DrawAngledText(ctr, angle, dimText);
        painter->DrawAngledText(ctr, angle, dimText, size);
 }
 
index 06f4496c15d44da73474035d00750bf081bdead0..8f689a80bd0e33cd2ef3000ba7bff14fea6d5c59 100644 (file)
@@ -221,15 +221,11 @@ void DrawingView::SetGridSize(uint32_t size)
 
 void DrawingView::UpdateGridBackground(void)
 {
-//was: 128
-//#define BG_BRUSH_SPAN 72
-#define BG_BRUSH_SPAN (gridPixels)
        // Transform the origin to Qt coordinates
        Vector pixmapOrigin = Painter::CartesianToQtCoords(Vector());
        int x = (int)pixmapOrigin.x;
        int y = (int)pixmapOrigin.y;
        // Use mod arithmetic to grab the correct swatch of background
-       // Problem with mod 128: Negative numbers screw it up... [FIXED]
 /*
 Negative numbers still screw it up... Need to think about what we're
 trying to do here. The fact that it worked with 72 seems to have been pure luck.
@@ -268,51 +264,33 @@ Which means we need to grab the sample from x = 3. @ x = -1:
    |   |   |   |
 
 Which means we need to grab the sample from x = 1. Which means we have to take
-the inverse of the modulus of gridPixels.
+the mirror of the modulus of gridPixels.
 
 Doing a mod of a negative number is problematic: 1st, the compiler converts the
 negative number to an unsigned int, then it does the mod. Gets you wrong answers
-most of the time, unless you use a power of 2. :-P
-
-This has been solved below:
-UGB: pmo=(2.000000,687.000000) X=2, X%48=2, new x=45
-UGB: pmo=(1.000000,687.000000) X=1, X%48=1, new x=46
-UGB: pmo=(0.000000,687.000000) X=0, X%48=0, new x=47
-UGB: pmo=(-1.000000,687.000000) X=-1, X%48=15, new x=1
-UGB: pmo=(-2.000000,686.000000) X=-2, X%48=14, new x=2
-UGB: pmo=(-3.000000,686.000000) X=-3, X%48=13, new x=3
-
-Problem with changing grid size causes x/y origin to be shown incorrectly:
-UGB: pmo=(10.000000,812.000000) X=10, X%12=10, new x=2
-UGB: pmo=(10.000000,812.000000) X=10, X%4=2,   new x=2
-UGB: pmo=(3.333333,818.666667)  X=3,  X%48=3,  new x=45
-UGB: pmo=(39.000000,782.000000) X=39, X%48=39, new x=9   <-- MMB move is here
-UGB: pmo=(39.000000,781.000000) X=39, X%48=39, new x=9
-
-
-
+most of the time, unless you use a power of 2. :-P So what we do here is just
+take the modulus of the negation, which means we don't have to worry about
+mirroring it later.
+
+The positive case looks gruesome (and it is) but it boils down to this: We take
+the modulus of the X coordinate, then mirror it by subtraction from the
+maximum (in this case, gridPixels). This gives us a number in the range of 1 to
+gridPixels. But we need the case where the result equalling gridPixels to be
+zero; so we do another modulus operation on the result to achieve this.
 */
-//printf("UGB: pmo=(%f,%f) X=%i, X%%%i=%i, ", pixmapOrigin.x, pixmapOrigin.y, x, BG_BRUSH_SPAN, x % BG_BRUSH_SPAN);
-//     x = (x < 0 ? 0 : BG_BRUSH_SPAN - 1) - (x % BG_BRUSH_SPAN);
-//     y = (y < 0 ? 0 : BG_BRUSH_SPAN - 1) - (y % BG_BRUSH_SPAN);
-//     x = (BG_BRUSH_SPAN - 1) - (x % BG_BRUSH_SPAN);
-//     y = (BG_BRUSH_SPAN - 1) - (y % BG_BRUSH_SPAN);
-//     x = (x < 0 ? 0 : BG_BRUSH_SPAN - 1) - ((x < 0 ? -x : x) % BG_BRUSH_SPAN);
        if (x < 0)
-               x = -x % BG_BRUSH_SPAN;
+               x = -x % gridPixels;
        else
-               x = (BG_BRUSH_SPAN - (x % BG_BRUSH_SPAN)) % BG_BRUSH_SPAN;
+               x = (gridPixels - (x % gridPixels)) % gridPixels;
 
-//     y = (y < 0 ? 0 : BG_BRUSH_SPAN - 1) - ((y < 0 ? -y : y) % BG_BRUSH_SPAN);
        if (y < 0)
-               y = -y % BG_BRUSH_SPAN;
+               y = -y % gridPixels;
        else
-               y = (BG_BRUSH_SPAN - (y % BG_BRUSH_SPAN)) % BG_BRUSH_SPAN;
-//printf("new x=%i\n", x);
+               y = (gridPixels - (y % gridPixels)) % gridPixels;
 
        // Here we grab a section of the bigger pixmap, so that the background
        // *looks* like it's scrolling...
-       QPixmap pm = gridBackground.copy(x, y, BG_BRUSH_SPAN, BG_BRUSH_SPAN);
+       QPixmap pm = gridBackground.copy(x, y, gridPixels, gridPixels);
        QPalette pal = palette();
        pal.setBrush(backgroundRole(), QBrush(pm));
        setAutoFillBackground(true);
@@ -398,11 +376,9 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
 }
 
 
-void DrawingView::resizeEvent(QResizeEvent * event)
+void DrawingView::resizeEvent(QResizeEvent * /*event*/)
 {
        Painter::screenSize = Vector(size().width(), size().height());
-//     Painter::screenSize = Vector(event->size().width(), event->size().height());
-//printf("DrawingView::resizeEvent: new size:
        UpdateGridBackground();
 }
 
index 2a5ed33eaef1a0f200b223d9145c1076d386d33b..6cfd91f8ef62641d6584158631c6a3834866532a 100644 (file)
@@ -119,32 +119,22 @@ void Painter::DrawAngledText(Vector center, double angle, QString text, double s
        // We may need this stuff... If dimension text is large enough.
 //     int textWidth = QFontMetrics(painter->font()).width(text);
 //     int textHeight = QFontMetrics(painter->font()).height();
-// NOTE: SCREEN_ZOOM is a kludge to make things look right at screen resolution...
-//     QRectF textBox(-100.0 * zoom * SCREEN_ZOOM, -100.0 * zoom * SCREEN_ZOOM, 200.0 * zoom * SCREEN_ZOOM, 200.0 * zoom * SCREEN_ZOOM);       // x, y, w, h; x/y = upper left corner
        QRectF textBox(-100.0 * zoom * size, -100.0 * zoom * size, 200.0 * zoom * size, 200.0 * zoom * size);   // x, y, w, h; x/y = upper left corner
 
        // This is in pixels. Might not render correctly at all zoom levels.
-       // Need to figure out if dimensions are always rendered at one size regardless of zoom,
-       // or if they have a definite size, and are thus zoomable.
-       // If zoomable, this is incorrect:
-       // (Added zoom, so this is correct now :-)
-//     float yOffset = -12.0 * zoom * SCREEN_ZOOM;
+       // Need to figure out if dimensions are always rendered at one size
+       // regardless of zoom, or if they have a definite size, and are thus
+       // zoomable.
        float yOffset = -12.0 * zoom * size;
 
        // Fix text so it isn't upside down...
        if ((angle > PI * 0.5) && (angle < PI * 1.5))
        {
                angle += PI;
-//             yOffset = 12.0 * zoom * SCREEN_ZOOM;
                yOffset = 12.0 * zoom * size;
        }
 
-#if 0
-       Vector offset = CartesianToQtCoords(Vector(0, yOffset));
-       textBox.translate(offset.x, offset.y);
-#else
        textBox.translate(0, yOffset);
-#endif
        painter->save();
        painter->translate(center.x, center.y);
        // Angles are backwards in the Qt coord system, so we flip ours...
@@ -258,16 +248,9 @@ void Painter::DrawArrowhead(Vector head, Vector tail, double size)
        Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
        Vector unit = Vector(head - tail).Unit();
 
-#if 0
-// NOTE: SCREEN_ZOOM is a kludge to make things look right at scale...
-       Point p1 = head - (unit * 9.0 * SCREEN_ZOOM);
-       Point p2 = p1 + (orthogonal * 3.0 * SCREEN_ZOOM);
-       Point p3 = p1 - (orthogonal * 3.0 * SCREEN_ZOOM);
-#else
        Point p1 = head - (unit * 9.0 * size);
        Point p2 = p1 + (orthogonal * 3.0 * size);
        Point p3 = p1 - (orthogonal * 3.0 * size);
-#endif
 
        Point p4 = CartesianToQtCoords(head);
        Point p5 = CartesianToQtCoords(p2);
index e992bbffd53aa5496bffde85c0ff6b543f4891fd..ab1433f9c6a5123e6ca6a8475cbe852210ecb933 100644 (file)
@@ -11,6 +11,7 @@
 // JLH  09/19/2006  Created this file\r
 // JLH  03/22/2011  Moved implementation of constructor from header to here\r
 // JLH  04/02/2011  Fixed divide-by-zero bug in Unit(), added Angle() function\r
+// JLH  08/04/2013  Added Parameter() function\r
 //\r
 \r
 #include "vector.h"\r
 #include <math.h>                                                              // For sqrt()\r
 #include "mathconstants.h"\r
 \r
-\r
 // Vector implementation\r
 \r
 Vector::Vector(double xx/*= 0*/, double yy/*= 0*/, double zz/*= 0*/): x(xx), y(yy), z(zz)\r
 {\r
 }\r
 \r
+\r
 Vector::Vector(Vector head, Vector tail): x(head.x - tail.x), y(head.y - tail.y), z(head.z - tail.z)\r
 {\r
 }\r
 \r
+\r
 Vector Vector::operator=(Vector const v)\r
 {\r
        x = v.x, y = v.y, z = v.z;\r
@@ -36,16 +38,19 @@ Vector Vector::operator=(Vector const v)
        return *this;\r
 }\r
 \r
+\r
 Vector Vector::operator+(Vector const v)\r
 {\r
        return Vector(x + v.x, y + v.y, z + v.z);\r
 }\r
 \r
+\r
 Vector Vector::operator-(Vector const v)\r
 {\r
        return Vector(x - v.x, y - v.y, z - v.z);\r
 }\r
 \r
+\r
 // Unary negation\r
 \r
 Vector Vector::operator-(void)\r
@@ -53,6 +58,7 @@ Vector Vector::operator-(void)
        return Vector(-x, -y, -z);\r
 }\r
 \r
+\r
 // Vector x constant\r
 \r
 Vector Vector::operator*(double const v)\r
@@ -60,6 +66,7 @@ Vector Vector::operator*(double const v)
        return Vector(x * v, y * v, z * v);\r
 }\r
 \r
+\r
 // Vector x constant\r
 \r
 Vector Vector::operator*(float const v)\r
@@ -67,6 +74,7 @@ Vector Vector::operator*(float const v)
        return Vector(x * v, y * v, z * v);\r
 }\r
 \r
+\r
 // Vector / constant\r
 \r
 Vector Vector::operator/(double const v)\r
@@ -74,6 +82,7 @@ Vector Vector::operator/(double const v)
        return Vector(x / v, y / v, z / v);\r
 }\r
 \r
+\r
 // Vector / constant\r
 \r
 Vector Vector::operator/(float const v)\r
@@ -81,6 +90,7 @@ Vector Vector::operator/(float const v)
        return Vector(x / v, y / v, z / v);\r
 }\r
 \r
+\r
 // Vector (cross) product\r
 \r
 Vector Vector::operator*(Vector const v)\r
@@ -89,6 +99,7 @@ Vector Vector::operator*(Vector const v)
        return Vector((y * v.z) - (z * v.y), (z * v.x) - (x * v.z), (x * v.y) - (y * v.x));\r
 }\r
 \r
+\r
 // Dot product\r
 \r
 double Vector::Dot(Vector const v)\r
@@ -106,6 +117,7 @@ Vector& Vector::operator*=(double const v)
        return *this;\r
 }\r
 \r
+\r
 // Vector / constant, self assigned\r
 \r
 Vector& Vector::operator/=(double const v)\r
@@ -124,6 +136,7 @@ Vector& Vector::operator+=(Vector const v)
        return *this;\r
 }\r
 \r
+\r
 // Vector + constant, self assigned\r
 \r
 Vector& Vector::operator+=(double const v)\r
@@ -133,6 +146,7 @@ Vector& Vector::operator+=(double const v)
        return *this;\r
 }\r
 \r
+\r
 // Vector - vector, self assigned\r
 \r
 Vector& Vector::operator-=(Vector const v)\r
@@ -142,6 +156,7 @@ Vector& Vector::operator-=(Vector const v)
        return *this;\r
 }\r
 \r
+\r
 // Vector - constant, self assigned\r
 \r
 Vector& Vector::operator-=(double const v)\r
@@ -151,18 +166,21 @@ Vector& Vector::operator-=(double const v)
        return *this;\r
 }\r
 \r
+\r
 // Check for equality\r
 bool Vector::operator==(Vector const v)\r
 {\r
        return (x == v.x && y == v.y && z == v.z ? true : false);\r
 }\r
 \r
+\r
 // Check for inequality\r
 bool Vector::operator!=(Vector const v)\r
 {\r
        return (x != v.x || y != v.y || z != v.z ? true : false);\r
 }\r
 \r
+\r
 Vector Vector::Unit(void)\r
 {\r
        double mag = Magnitude();\r
@@ -174,11 +192,13 @@ Vector Vector::Unit(void)
        return Vector(x / mag, y / mag, z / mag);\r
 }\r
 \r
+\r
 double Vector::Magnitude(void)\r
 {\r
        return sqrt(x * x + y * y + z * z);\r
 }\r
 \r
+\r
 double Vector::Angle(void)\r
 {\r
        // acos returns a value between zero and PI, which means we don't know which\r
@@ -190,6 +210,7 @@ double Vector::Angle(void)
        return correctedAngle;\r
 }\r
 \r
+\r
 bool Vector::isZero(double epsilon/*= 1e-6*/)\r
 {\r
        return (fabs(x) < epsilon && fabs(y) < epsilon && fabs(z) < epsilon ? true : false);\r
@@ -203,6 +224,7 @@ double Vector::Dot(Vector v1, Vector v2)
        return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);\r
 }\r
 \r
+\r
 double Vector::Magnitude(Vector v1, Vector v2)\r
 {\r
        double xx = v1.x - v2.x;\r
@@ -210,3 +232,23 @@ double Vector::Magnitude(Vector v1, Vector v2)
        double zz = v1.z - v2.z;\r
        return sqrt(xx * xx + yy * yy + zz * zz);\r
 }\r
+\r
+\r
+// Returns the parameter of a point in space to this vector. If the parameter\r
+// is between 0 and 1, the normal of the vector to the point is on the vector.\r
+double Vector::Parameter(Vector v1, Vector v2, Vector p)\r
+{\r
+       // Geometric interpretation:\r
+       // The parameterized point on the vector lineSegment is where the normal of\r
+       // the lineSegment to the point intersects lineSegment. If the pp < 0, then\r
+       // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the\r
+       // perpendicular lies beyond the 2nd endpoint.\r
+\r
+       Vector lineSegment = v2 - v1;\r
+       double magnitude = lineSegment.Magnitude();\r
+       Vector pointSegment = p - v1;\r
+       double t = lineSegment.Dot(pointSegment) / (magnitude * magnitude);\r
+\r
+       return t;\r
+}\r
+\r
index 6f11a32e94b850efa31515c122c28aa2c75faaca..0e7fc864f371c4d3c3478a47c9119c583ff3948d 100644 (file)
@@ -47,6 +47,7 @@ class Vector
 \r
                static double Dot(Vector v1, Vector v2);\r
                static double Magnitude(Vector v1, Vector v2);\r
+               static double Parameter(Vector v1, Vector v2, Vector p);\r
 \r
        public:\r
                double x, y, z;\r