]> Shamusworld >> Repos - architektonas/commitdiff
Added base units & display style to drawing.
authorShamus Hammons <jlhamm@acm.org>
Thu, 6 Jan 2022 18:50:39 +0000 (12:50 -0600)
committerShamus Hammons <jlhamm@acm.org>
Thu, 6 Jan 2022 18:50:39 +0000 (12:50 -0600)
This also gets saved with the drawing; the ATNS file format stays at
v1.2 as these will be set to defaults if they are missing.  Also, there
is now a dialog to change these setting per drawing; currently any
change of base unit to a current drawing does no unit conversion to the
drawing itself.  This will be rectified in a future revision.

architektonas.pro
src/applicationwindow.cpp
src/applicationwindow.h
src/drawingsettingsdlg.cpp [new file with mode: 0644]
src/drawingsettingsdlg.h [new file with mode: 0644]
src/drawingview.cpp
src/drawingview.h
src/fileio.cpp
src/structs.h
src/units.cpp [new file with mode: 0644]
src/units.h [new file with mode: 0644]

index 86dd646822159c53a3e393a767da1b5539dfa4a3..5f68a703718f537e2aa4a1761863ff0942db433a 100644 (file)
@@ -54,6 +54,7 @@ HEADERS = \
        src/blockwidget.h \
        src/commandprocessor.h \
        src/consolewidget.h \
+       src/drawingsettingsdlg.h \
        src/drawingview.h \
        src/fileio.h \
        src/generaltab.h \
@@ -70,6 +71,7 @@ HEADERS = \
        src/rect.h \
        src/settingsdialog.h \
        src/structs.h \
+       src/units.h \
        src/utils.h \
        src/vector.h
 
@@ -81,6 +83,7 @@ SOURCES = \
        src/blockwidget.cpp \
        src/commandprocessor.cpp \
        src/consolewidget.cpp \
+       src/drawingsettingsdlg.cpp \
        src/drawingview.cpp \
        src/fileio.cpp \
        src/generaltab.cpp \
@@ -95,6 +98,7 @@ SOURCES = \
        src/promptlineedit.cpp \
        src/rect.cpp \
        src/settingsdialog.cpp \
+       src/units.cpp \
        src/utils.cpp \
        src/vector.cpp
 
index 8c114c8d045c43723dbdd81d7e492a4d89f770e3..8bbdbc1c5646c8c996fdf33244b0f0995f711fa7 100644 (file)
@@ -33,6 +33,7 @@
 #include "blockwidget.h"
 #include "commandprocessor.h"
 #include "consolewidget.h"
+#include "drawingsettingsdlg.h"
 #include "drawingview.h"
 #include "fileio.h"
 #include "generaltab.h"
@@ -596,7 +597,7 @@ void ApplicationWindow::SetInternalToolStates(void)
        else
                Global::tool = TTNone;
 
-       cw->SetToolPrompt();//cw->cmdline);
+       cw->SetToolPrompt();
        drawing->update();
 }
 
@@ -618,6 +619,25 @@ void ApplicationWindow::Settings(void)
        WriteSettings();
 }
 
+void ApplicationWindow::DrawingSettings(void)
+{
+       DrawingSettingsDlg dlg(this);
+       dlg.baseUnit->setCurrentIndex(drawing->document.baseUnit);
+       dlg.unitStyle->setCurrentIndex(drawing->document.unitStyle);
+       dlg.decimalPrecision->setCurrentIndex(drawing->document.decimalPrecision);
+       dlg.fractionalPrecision->setCurrentIndex(drawing->document.fractionalPrecision);
+
+       if (dlg.exec() == false)
+               return;
+
+       // Deal with stuff here (since user hit "OK" button...)
+       drawing->document.baseUnit = dlg.baseUnit->currentIndex();
+       drawing->document.unitStyle = dlg.unitStyle->currentIndex();
+       drawing->document.decimalPrecision= dlg.decimalPrecision->currentIndex();
+       drawing->document.fractionalPrecision = dlg.fractionalPrecision->currentIndex();
+       drawing->update();
+}
+
 //
 // Group a bunch of selected objects (which can include other groups) together
 // or ungroup a selected group.
@@ -904,6 +924,9 @@ void ApplicationWindow::CreateActions(void)
        settingsAct = CreateAction(tr("&Settings"), tr("Settings"), tr("Change certain defaults for Architektonas."), QIcon(":/res/settings.png"), QKeySequence());
        connect(settingsAct, SIGNAL(triggered()), this, SLOT(Settings()));
 
+       drawingSettingsAct = CreateAction(tr("&Drawing Settings"), tr("Drawing settings"), tr("Change certain defaults for the current drawing."), QIcon(":/res/settings.png"), QKeySequence());
+       connect(drawingSettingsAct, SIGNAL(triggered()), this, SLOT(DrawingSettings()));
+
        groupAct = CreateAction(tr("&Group"), tr("Group"), tr("Group/ungroup selected objects."), QIcon(":/res/group-tool.png"), QKeySequence("g"));
        connect(groupAct, SIGNAL(triggered()), this, SLOT(HandleGrouping()));
 
@@ -1044,6 +1067,7 @@ void ApplicationWindow::CreateMenus(void)
        menu->addAction(addSplineAct);
        menu->addAction(addDimensionAct);
        menu->addSeparator();
+       menu->addAction(drawingSettingsAct);
        menu->addAction(settingsAct);
 
        menu = menuBar()->addMenu(tr("&Help"));
index be245b08987586d2f2ce022396c1776a1b2e595d..8b9921818107f041f690443d450326acda88e484 100644 (file)
@@ -54,6 +54,7 @@ class ApplicationWindow: public QMainWindow
                void ZoomOutTool(void);
                void HelpAbout(void);
                void Settings(void);
+               void DrawingSettings(void);
                void HandleGrouping(void);
                void HandleConnection(void);
                void HandleDisconnection(void);
@@ -103,6 +104,7 @@ class ApplicationWindow: public QMainWindow
                QAction * fileCloseAct;
                QAction * exitAct;
                QAction * settingsAct;
+               QAction * drawingSettingsAct;
                QAction * fixAngleAct;
                QAction * fixLengthAct;
                QAction * deleteAct;
diff --git a/src/drawingsettingsdlg.cpp b/src/drawingsettingsdlg.cpp
new file mode 100644 (file)
index 0000000..ede8cb9
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// drawingsettingsdlg.cpp: Dialog for changing a drawing's settings
+//
+// Part of the Architektonas Project
+// (C) 2021 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  12/31/2021  Created this file
+
+#include "drawingsettingsdlg.h"
+
+DrawingSettingsDlg::DrawingSettingsDlg(QWidget * parent/*= 0*/): QDialog(parent), baseUnit(new QComboBox(this)), unitStyle(new QComboBox(this)), decimalPrecision(new QComboBox(this)), fractionalPrecision(new QComboBox(this))
+{
+       QStringList buList = { "Inch", "Foot", "Yard", "Mile", "mm", "cm", "m", "km" };
+       QStringList usList = { "Decimal", "Fractional" };
+       QStringList dpList = { "0.1", "0.01", "0.001", "0.0001", "0.00001", "0.000001" };
+       QStringList fpList = { "1/2", "1/4", "1/8", "1/16", "1/32", "1/64" };
+
+       baseUnit->insertItems(0, buList);
+       unitStyle->insertItems(0, usList);
+       decimalPrecision->insertItems(0, dpList);
+       fractionalPrecision->insertItems(0, fpList);
+
+       QFormLayout * fl = new QFormLayout;
+
+       fl->addRow(tr("Base Unit:"), baseUnit);
+       fl->addRow(tr("Unit Style:"), unitStyle);
+       fl->addRow(tr("Decimal Precision:"), decimalPrecision);
+       fl->addRow(tr("Fractional Precision:"), fractionalPrecision);
+
+       buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+       connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+       connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+       QVBoxLayout * mainLayout = new QVBoxLayout;
+       mainLayout->addLayout(fl);
+       mainLayout->addWidget(buttonBox);
+       setLayout(mainLayout);
+
+       setWindowTitle(tr("Drawing Settings"));
+}
+
+DrawingSettingsDlg::~DrawingSettingsDlg()
+{
+}
diff --git a/src/drawingsettingsdlg.h b/src/drawingsettingsdlg.h
new file mode 100644 (file)
index 0000000..19c9d98
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __DRAWINGSETTINGSDLG_H__
+#define __DRAWINGSETTINGSDLG_H__
+
+#include <QtWidgets>
+
+class DrawingSettingsDlg: public QDialog
+{
+       Q_OBJECT
+
+       public:
+               DrawingSettingsDlg(QWidget * parent = 0);
+               ~DrawingSettingsDlg();
+
+       private:
+               QDialogButtonBox * buttonBox;
+
+       public:
+               QComboBox * baseUnit;
+               QComboBox * unitStyle;
+               QComboBox * decimalPrecision;
+               QComboBox * fractionalPrecision;
+};
+
+#endif // __DRAWINGSETTINGSDLG_H__
index 3baa2d77eed71712dd168fa79ff6ddb73e016faa..3b6f92c6663c363bba9b1cf68e006793f101a7e0 100644 (file)
@@ -41,6 +41,7 @@
 #include "painter.h"
 #include "penwidget.h"
 #include "structs.h"
+#include "units.h"
 #include "utils.h"
 
 #define BACKGROUND_MAX_SIZE    512
@@ -52,8 +53,9 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10), supressSelected(false),
        document(true),
-       gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false),
-       hoveringIntersection(false), dragged(NULL), draggingObject(false),
+       gridPixels(0), collided(false), scrollDrag(false),
+       hoverPointValid(false), hoveringIntersection(false),
+       dragged(NULL), draggingObject(false),
        angleSnap(false), dirty(false)
 {
 //wtf? doesn't work except in c++11??? document = { 0 };
@@ -556,20 +558,7 @@ void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool
                        painter->SetFont(QFont("Arial", 8.0 * Global::zoom * scaledThickness));
                        Point ctr = p2 + (Vector(p2, p1) / 2.0);
 
-                       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);
-                       }
+                       QString dimText = GetDimensionText(&document, length);
 
 /*
 Where is the text offset?  It looks like it's drawing in the center, but obviously it isn't.  It isn't here, it's in Painter::DrawAngledText().
@@ -3034,7 +3023,7 @@ N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not*
                        obj->radius[0] = Vector::Magnitude(obj->p[0], point);
 
                        QString text = QObject::tr("Radius: %1\nScale: %2%");
-                       informativeText = text.arg(obj->radius[0], 0, 'd', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0);
+                       informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
                }
 
                break;
index 5906766d35b6bd459e0c2ccf9cdca55405a2f60a..0d483926f049e62787b45bce2c7fa6a8a1a164c0 100644 (file)
@@ -85,16 +85,16 @@ class DrawingView: public QWidget
 
        private:
                QPixmap gridBackground;
-               double scale;                                                   // Window scaling factor
-               int32_t offsetX, offsetY;                               // Window offsets
+               double scale;                                           // Window scaling factor
+               int32_t offsetX, offsetY;                       // Window offsets
                bool supressSelected;
                QCursor curMarker;
                QCursor curDropper;
                uint32_t currentSelect;
        public:
                Container document;
-               uint32_t gridPixels;                                    // Grid size in pixels
-               double gridPixelsF;                                             // Grid size in pixels (float)
+               uint32_t gridPixels;                            // Grid size in pixels
+               double gridPixelsF;                                     // Grid size in pixels (float)
                bool collided;
                bool scrollDrag;
                Vector oldPoint;
index 1b11902e37b672f1f6a72bd6dc443894acce5efd..3ce447040014fe9ea7e53bb5d4be90bda16f0521 100644 (file)
@@ -108,11 +108,8 @@ OTHER CONSIDERATIONS:
   - Need to figure out how to store the Layer list (should layer list be optional?)
   - Need to figure out how to store the Block list and blocks
 
-
 */
 
-//enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
-//     OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile };
 enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
 
 // Instantiate class variables
@@ -127,6 +124,12 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
           Container, otherwise it enumerates all objects within itself. */
 
        fprintf(file, "ARCHITEKTONAS DRAWING V1.2\n");
+       fprintf(file, "PROPERTIES 4\n");
+       fprintf(file, "BASE_UNIT %i\n", c->baseUnit);
+       fprintf(file, "UNIT_STYLE %i\n", c->unitStyle);
+       fprintf(file, "DEC_PREC %i\n", c->decimalPrecision);
+       fprintf(file, "FRAC_PREC %i\n", c->fractionalPrecision);
+
        fprintf(file, "LAYERS %i\n", Global::numLayers);
 
        for(int i=0; i<Global::numLayers; i++)
@@ -156,7 +159,6 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
        else if (version == 1.2f)
                return LoadVersion1_2(file, drawing);
 
-//printf("LoadAtnsFile: Could not locate version! (version=%f)\n", version);
        return false;
 }
 
@@ -272,10 +274,21 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
 
 /*static*/ bool FileIO::LoadVersion1_2(FILE * file, Container * drawing)
 {
-       int hidden, locked;
+       int hidden, locked, props = 0;
        char textBuffer[65536];
 
-       // Load layer information first
+       // Load drawing properties, if any, first
+       fscanf(file, "PROPERTIES %i\n", &props);
+
+       if (props == 4)
+       {
+               fscanf(file, "BASE_UNIT %i\n", &(drawing->baseUnit));
+               fscanf(file, "UNIT_STYLE %i\n", &(drawing->unitStyle));
+               fscanf(file, "DEC_PREC %i\n", &(drawing->decimalPrecision));
+               fscanf(file, "FRAC_PREC %i\n", &(drawing->fractionalPrecision));
+       }
+
+       // Load layer information next
        fscanf(file, "LAYERS %i\n", &Global::numLayers);
 
        for(int i=0; i<Global::numLayers; i++)
@@ -466,7 +479,6 @@ if (errno)
        case OTPolygon:
                break;
        case OTDimension:
-//             fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, dimensionType);
                fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype, ((Dimension *)obj)->offset);
                break;
        case OTSpline:
index d0dbb55611ae90b00a63f454c3727930f50d5482..47d8d85a50795519943efebfea49879502c303e2 100644 (file)
@@ -156,7 +156,12 @@ struct Container {
        bool topLevel;
        Object * clicked;
 
-       Container(bool tl = false): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL) {}
+       int baseUnit;            // Type of BasicUnit as seen above
+       int unitStyle;           // 0 = decimal, 1 = fractional
+       int decimalPrecision;    // 0-5, which, +1, is # of decimal places
+       int fractionalPrecision; // 0-5, which, +1, is 1/(2^n)
+
+       Container(bool tl = false): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL), baseUnit(0), unitStyle(0), decimalPrecision(3), fractionalPrecision(4) {}
        void Add(void * obj) { objects.push_back(obj); }
        void Add(VPVector objs) { objects.insert(objects.end(), objs.begin(), objs.end()); }
 //     void DeleteContents(void) {}
diff --git a/src/units.cpp b/src/units.cpp
new file mode 100644 (file)
index 0000000..7b203a1
--- /dev/null
@@ -0,0 +1,130 @@
+//
+// units.cpp: Unit conversion/description
+//
+// Part of the Architektonas Project
+// (C) 2022 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  01/04/2022  Created this file
+
+#include "units.h"
+
+QString GetDimensionText(Container * c, double length)
+{
+       QString dimText;
+
+       if (c->unitStyle == 0)
+       {
+               // Decimal style
+               int decPrecision = c->decimalPrecision + 1;
+
+               if (c->baseUnit == BUInch)
+               {
+                       dimText = QString("%1\"").arg(length, 0, 'f', decPrecision);
+               }
+               else if (c->baseUnit == BUFoot)
+               {
+                       double feet = (double)((int)length);
+                       double inches = (length - feet) * 12.0;
+
+                       QString ftText = (feet != 0 ? QString("%1'").arg(feet) : "");
+                       QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : "");
+
+                       dimText = QString("%1%2").arg(ftText).arg(inText).trimmed();
+               }
+               else if (c->baseUnit == BUYard)
+               {
+                       double yards = (double)((int)length);
+                       double feet = (length - yards) * 3.0;
+                       double inches = (feet - ((int)feet)) * 12.0;
+                       feet = (double)((int)feet); // Integerize the feet now...
+
+                       QString ydText = (yards != 0 ? QString("%1 yd").arg(yards) : "");
+                       QString ftText = (feet != 0 ? QString(" %1'").arg(feet) : "");
+                       QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : "");
+
+                       dimText = QString("%1%2%3")
+                               .arg(ydText)
+                               .arg(ftText)
+                               .arg(inText)
+                               .trimmed();
+               }
+               else // mile, mm, cm, m, km
+               {
+                       dimText = QString("%1 %2")
+                               .arg(length, 0, 'f', decPrecision)
+                               .arg(buShortName[c->baseUnit]);
+               }
+       }
+       else
+       {
+               // Fractional style
+               int fracPrecision = 1 << (c->fractionalPrecision + 1);
+
+               if (c->baseUnit == BUInch)
+               {
+                       dimText = MakeFraction(length, fracPrecision) + QChar('"');
+               }
+               else if (c->baseUnit == BUFoot)
+               {
+                       double feet = (double)((int)length);
+                       double inches = (length - feet) * 12.0;
+
+                       QString ftText = (feet != 0 ? QString("%1'").arg(feet) : "");
+                       QString inText = (inches != 0 ? MakeFraction(inches, fracPrecision) + QChar('"') : "");
+
+                       dimText = QString("%1 %2").arg(ftText).arg(inText).trimmed();
+               }
+               else
+               {
+                       dimText = QString("%1 %2").arg(MakeFraction(length, fracPrecision)).arg(buShortName[c->baseUnit]);
+               }
+       }
+
+       return dimText;
+}
+
+//
+// Create a string that represents the passed in double as a proper fraction
+// with the given precision.  Fractions are rounded to the given precision
+// (which represents the denominator of the fraction).
+//
+QString MakeFraction(double num, int precision)
+{
+       int intPart = (int)num;
+       double fraction = num - (double)intPart;
+       int numerator = (int)(((double)precision * fraction) + 0.5);
+
+       // There's a chance we rounded up to the next whole number; if so, we fix
+       // that here.
+       if (numerator == precision)
+       {
+               intPart++;
+               numerator = 0;
+       }
+
+       // Reduce the fraction by casting out factors of two (we assume the
+       // precision will always be a power of two); that is, if there is a
+       // denominator to reduce.
+       if (numerator > 0)
+       {
+               // Divide fraction by two while the denominator is not odd.  N.B.: This
+               // will always end, as any non-zero number will eventually have a 1-bit
+               // in it somewhere, which we shift down to the low bit position with
+               // each iteration.
+               while ((numerator & 0x01) == 0)
+               {
+                       numerator /= 2;
+                       precision /= 2;
+               }
+       }
+
+       QString intText = (intPart != 0 ? QString("%1").arg(intPart) : "");
+       QString fracText = (numerator != 0 ? QString(" %1/%2").arg(numerator).arg(precision) : "");
+
+       return QString("%1%2").arg(intText).arg(fracText).trimmed();
+}
diff --git a/src/units.h b/src/units.h
new file mode 100644 (file)
index 0000000..e372aff
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __UNITS_H__
+#define __UNITS_H__
+
+#include <QString>
+#include "structs.h"
+
+#define INCHES_TO_MM  25.4
+#define MM_TO_INCHES  (1.0 / 25.4)
+
+QString GetDimensionText(Container *, double);
+QString MakeFraction(double, int);
+
+#endif // __UNITS_H__