2 // units.cpp: Unit conversion/description
4 // Part of the Architektonas Project
5 // (C) 2022 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
8 // JLH = James Hammons <jlhamm@acm.org>
11 // --- ---------- ------------------------------------------------------------
12 // JLH 01/04/2022 Created this file
16 QString GetDimensionText(Container * c, double length)
20 if (c->unitStyle == 0)
23 int decPrecision = c->decimalPrecision + 1;
25 if (c->baseUnit == BUInch)
27 dimText = QString("%1\"").arg(length, 0, 'f', decPrecision);
29 else if (c->baseUnit == BUFoot)
31 double feet = (double)((int)length);
32 double inches = (length - feet) * 12.0;
34 QString ftText = (feet != 0 ? QString("%1'").arg(feet) : "");
35 QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : "");
37 dimText = QString("%1%2").arg(ftText).arg(inText).trimmed();
39 else if (c->baseUnit == BUYard)
41 double yards = (double)((int)length);
42 double feet = (length - yards) * 3.0;
43 double inches = (feet - ((int)feet)) * 12.0;
44 feet = (double)((int)feet); // Integerize the feet now...
46 QString ydText = (yards != 0 ? QString("%1 yd").arg(yards) : "");
47 QString ftText = (feet != 0 ? QString(" %1'").arg(feet) : "");
48 QString inText = (inches != 0 ? QString(" %1\"").arg(inches, 0, 'f', decPrecision) : "");
50 dimText = QString("%1%2%3")
56 else // mile, mm, cm, m, km
58 dimText = QString("%1 %2")
59 .arg(length, 0, 'f', decPrecision)
60 .arg(buShortName[c->baseUnit]);
66 int fracPrecision = 1 << (c->fractionalPrecision + 1);
68 if (c->baseUnit == BUInch)
70 dimText = MakeFraction(length, fracPrecision) + QChar('"');
72 else if (c->baseUnit == BUFoot)
74 double feet = (double)((int)length);
75 double inches = (length - feet) * 12.0;
77 QString ftText = (feet != 0 ? QString("%1'").arg(feet) : "");
78 QString inText = (inches != 0 ? MakeFraction(inches, fracPrecision) + QChar('"') : "");
80 dimText = QString("%1 %2").arg(ftText).arg(inText).trimmed();
84 dimText = QString("%1 %2").arg(MakeFraction(length, fracPrecision)).arg(buShortName[c->baseUnit]);
92 // Create a string that represents the passed in double as a proper fraction
93 // with the given precision. Fractions are rounded to the given precision
94 // (which represents the denominator of the fraction).
96 QString MakeFraction(double num, int precision)
98 int intPart = (int)num;
99 double fraction = num - (double)intPart;
100 int numerator = (int)(((double)precision * fraction) + 0.5);
102 // There's a chance we rounded up to the next whole number; if so, we fix
104 if (numerator == precision)
110 // Reduce the fraction by casting out factors of two (we assume the
111 // precision will always be a power of two); that is, if there is a
112 // denominator to reduce.
115 // Divide fraction by two while the denominator is not odd. N.B.: This
116 // will always end, as any non-zero number will eventually have a 1-bit
117 // in it somewhere, which we shift down to the low bit position with
119 while ((numerator & 0x01) == 0)
126 QString intText = (intPart != 0 ? QString("%1").arg(intPart) : "");
127 QString fracText = (numerator != 0 ? QString(" %1/%2").arg(numerator).arg(precision) : "");
129 return QString("%1%2").arg(intText).arg(fracText).trimmed();