]> Shamusworld >> Repos - architektonas/blobdiff - src/units.cpp
Added base units & display style to drawing.
[architektonas] / src / units.cpp
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();
+}