X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Funits.cpp;fp=src%2Funits.cpp;h=7b203a16f3c93677388cb971b263efb1b58498eb;hb=41644f6a841b45cb6f1f7a96c93fd550f67a7974;hp=0000000000000000000000000000000000000000;hpb=d9f34cb7917e396a1df805687234d5473d82283b;p=architektonas diff --git a/src/units.cpp b/src/units.cpp new file mode 100644 index 0000000..7b203a1 --- /dev/null +++ b/src/units.cpp @@ -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 +// +// 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(); +}