1
/***************************************************************************
2
* Copyright (c) 2009 Jürgen Riegel <FreeCAD@juergen-riegel.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
24
#include "PreCompiled.h"
35
#include "UnitsSchemaImperial1.h"
42
UnitsSchemaImperial1::schemaTranslate(const Quantity& quant, double& factor, QString& unitString)
44
double UnitValue = std::abs(quant.getValue());
45
Unit unit = quant.getUnit();
46
// for imperial user/programmer mind; UnitValue is in internal system, that means
47
// mm/kg/s. And all combined units have to be calculated from there!
49
// now do special treatment on all cases seems necessary:
50
if (unit == Unit::Length) { // Length handling ============================
51
if (UnitValue < 0.00000254) { // smaller then 0.001 thou -> inch and scientific notation
52
unitString = QString::fromLatin1("in");
55
else if (UnitValue < 2.54) { // smaller then 0.1 inch -> Thou (mil)
56
unitString = QString::fromLatin1("thou");
59
else if (UnitValue < 304.8) {
60
unitString = QString::fromLatin1("\"");
63
else if (UnitValue < 914.4) {
64
unitString = QString::fromLatin1("\'");
67
else if (UnitValue < 1609344.0) {
68
unitString = QString::fromLatin1("yd");
71
else if (UnitValue < 1609344000.0) {
72
unitString = QString::fromLatin1("mi");
75
else { // bigger then 1000 mi -> scientific notation
76
unitString = QString::fromLatin1("in");
80
else if (unit == Unit::Angle) {
81
unitString = QString::fromUtf8("\xC2\xB0");
84
else if (unit == Unit::Area) {
85
// TODO: Cascade for the Areas
86
// default action for all cases without special treatment:
87
unitString = QString::fromLatin1("in^2");
90
else if (unit == Unit::Volume) {
91
// TODO: Cascade for the Volume
92
// default action for all cases without special treatment:
93
unitString = QString::fromLatin1("in^3");
96
else if (unit == Unit::Mass) {
97
// TODO: Cascade for the weights
98
// default action for all cases without special treatment:
99
unitString = QString::fromLatin1("lb");
102
else if (unit == Unit::Pressure) {
103
if (UnitValue < 6894.744) { // psi is the smallest
104
unitString = QString::fromLatin1("psi");
105
factor = 6.894744825494;
107
else if (UnitValue < 6894744.825) {
108
unitString = QString::fromLatin1("ksi");
109
factor = 6894.744825494;
111
else { // bigger then 1000 ksi -> psi + scientific notation
112
unitString = QString::fromLatin1("psi");
113
factor = 6.894744825494;
116
else if (unit == Unit::Stiffness) { // Conversion to lbf/in
117
unitString = QString::fromLatin1("lbf/in");
118
factor = 4.448222 / 0.0254;
120
else if (unit == Unit::Velocity) {
121
unitString = QString::fromLatin1("in/min");
125
// default action for all cases without special treatment:
126
unitString = quant.getUnit().getString();
130
return toLocale(quant, factor, unitString);
133
QString UnitsSchemaImperialDecimal::schemaTranslate(const Base::Quantity& quant,
137
// double UnitValue = std::abs(quant.getValue());
138
Unit unit = quant.getUnit();
139
// for imperial user/programmer mind; UnitValue is in internal system, that means
140
// mm/kg/s. And all combined units have to be calculated from there!
142
// now do special treatment on all cases seems necessary:
143
if (unit == Unit::Length) { // Length handling ============================
144
unitString = QString::fromLatin1("in");
147
else if (unit == Unit::Angle) {
148
unitString = QString::fromUtf8("\xC2\xB0");
151
else if (unit == Unit::Area) {
152
// TODO: Cascade for the Areas
153
// default action for all cases without special treatment:
154
unitString = QString::fromLatin1("in^2");
157
else if (unit == Unit::Volume) {
158
// TODO: Cascade for the Volume
159
// default action for all cases without special treatment:
160
unitString = QString::fromLatin1("in^3");
163
else if (unit == Unit::Mass) {
164
// TODO: Cascade for the weights
165
// default action for all cases without special treatment:
166
unitString = QString::fromLatin1("lb");
169
else if (unit == Unit::Pressure) {
170
unitString = QString::fromLatin1("psi");
171
factor = 6.894744825494;
173
else if (unit == Unit::Stiffness) {
174
unitString = QString::fromLatin1("lbf/in");
175
factor = 4.448222 / 0.0254;
177
else if (unit == Unit::Velocity) {
178
unitString = QString::fromLatin1("in/min");
181
else if (unit == Unit::Acceleration) {
182
unitString = QString::fromLatin1("in/min^2");
183
factor = 25.4 / 3600;
186
// default action for all cases without special treatment:
187
unitString = quant.getUnit().getString();
191
return toLocale(quant, factor, unitString);
194
QString UnitsSchemaImperialBuilding::schemaTranslate(const Quantity& quant,
198
// this schema expresses distances in feet + inches + fractions
199
// ex: 3'- 4 1/4" with proper rounding
200
Unit unit = quant.getUnit();
201
if (unit == Unit::Length) {
202
unitString = QString::fromLatin1("in");
205
// Total number of inches to format
206
double totalInches = std::abs(quant.getValue()) / factor;
208
// minimum denominator (8 for 1/8, 16 for 1/16, etc)
212
int feet {}; // whole feet
213
int inches {}; // whole inches
214
int num {}, den {}; // numerator and denominator of fractional val
215
std::stringstream output; // output stream
217
// Intermediate values
218
int ntot {}; // total fractional units
219
int a {}, b {}, d {}; // used to compute greatest common denominator
220
int tmp {}; // temporary variable for GCD
222
// Get the current user specified minimum denominator
223
minden = quant.getFormat().getDenominator();
225
// Compute and round the total number of fractional units
226
ntot = static_cast<int>(std::round(totalInches * static_cast<double>(minden)));
228
// If this is zero, nothing to do but return
230
return QString::fromLatin1("0");
233
// Compute the whole number of feet and remaining units
234
feet = static_cast<int>(std::floor(ntot / (12 * minden)));
235
ntot = ntot - 12 * minden * feet;
237
// Compute the remaining number of whole inches
238
inches = static_cast<int>(std::floor(ntot / minden));
240
// Lastly the fractional quantities
241
num = ntot - inches * minden;
244
// If numerator is not zero, compute greatest common divisor and reduce
262
// Process into string. Start with negative sign if quantity is less
265
if (quant.getValue() < 0) {
273
bool trailingNumber = false;
274
// Print feet if we have any
276
output << feet << "'";
277
trailingNumber = true;
279
// Print whole inches if we have any
281
if (trailingNumber) {
284
output << inches << "\"";
285
trailingNumber = true;
287
// Print fractional inches if we have any
289
if (trailingNumber) {
290
output << " " << plusOrMinus << " ";
292
output << num << "/" << den << "\"";
296
return QString::fromLatin1(output.str().c_str());
298
else if (unit == Unit::Angle) {
299
unitString = QString::fromUtf8("\xC2\xB0");
302
else if (unit == Unit::Area) {
303
unitString = QString::fromLatin1("sqft");
306
else if (unit == Unit::Volume) {
307
unitString = QString::fromLatin1("cft");
308
factor = 28316846.592;
310
else if (unit == Unit::Velocity) {
311
unitString = QString::fromLatin1("in/min");
315
unitString = quant.getUnit().getString();
319
return toLocale(quant, factor, unitString);
322
QString UnitsSchemaImperialCivil::schemaTranslate(const Base::Quantity& quant,
326
// double UnitValue = std::abs(quant.getValue());
327
Unit unit = quant.getUnit();
328
// for imperial user/programmer mind; UnitValue is in internal system, that means
329
// mm/kg/s. And all combined units have to be calculated from there!
331
// now do special treatment on all cases seems necessary:
332
if (unit == Unit::Length) { // Length handling ============================
333
unitString = QString::fromLatin1("ft"); // always ft
334
factor = 304.8; // 12 * 25.4
336
else if (unit == Unit::Area) {
337
unitString = QString::fromLatin1("ft^2"); // always sq.ft
340
else if (unit == Unit::Volume) {
341
unitString = QString::fromLatin1("ft^3"); // always cu. ft
342
factor = 28316846.592;
344
else if (unit == Unit::Mass) {
345
unitString = QString::fromLatin1("lb"); // always lbs.
348
else if (unit == Unit::Pressure) {
349
unitString = QString::fromLatin1("psi");
350
factor = 6.894744825494;
352
else if (unit == Unit::Stiffness) {
353
unitString = QString::fromLatin1("lbf/in");
354
factor = 4.448222 / 0.0254;
356
else if (unit == Unit::Velocity) {
357
unitString = QString::fromLatin1("mph");
358
factor = 447.04; // 1mm/sec => mph
360
// this schema expresses angles in degrees + minutes + seconds
361
else if (unit == Unit::Angle) {
362
unitString = QString::fromUtf8("deg");
363
QString degreeString = QString::fromUtf8("\xC2\xB0"); // degree symbol
364
QString minuteString = QString::fromUtf8("\xE2\x80\xB2"); // prime symbol
365
QString secondString = QString::fromUtf8("\xE2\x80\xB3"); // double prime symbol
366
factor = 1.0; // 1deg = 1"\xC2\xB0 "
368
double totalDegrees = quant.getValue() / factor;
369
double wholeDegrees = std::floor(totalDegrees);
370
double sumMinutes = totalDegrees * 60.0; // quant as minutes
371
double rawMinutes = sumMinutes - wholeDegrees * 60.0;
372
double wholeMinutes = std::floor(rawMinutes);
373
double sumSeconds = totalDegrees * 3600.0; // quant as seconds
374
double rawSeconds = sumSeconds - (wholeDegrees * 3600.0) - (wholeMinutes * 60);
376
int outDeg = static_cast<int>(wholeDegrees);
377
int outMin = static_cast<int>(wholeMinutes);
378
int outSec = static_cast<int>(std::round(rawSeconds));
380
std::stringstream output;
381
output << outDeg << degreeString.toUtf8().constData();
382
if ((outMin > 0) || (outSec > 0)) {
383
output << outMin << minuteString.toUtf8().constData();
386
output << outSec << secondString.toUtf8().constData();
388
// uncomment this for decimals on seconds
389
// if (remainSeconds < (1.0 * pow(10.0,-Base::UnitsApi::getDecimals())) ) {
390
// //NOP too small to display
392
// output << std::setprecision(Base::UnitsApi::getDecimals()) << std::fixed <<
393
// rawSeconds << secondString.toStdString();
395
return QString::fromUtf8(output.str().c_str());
398
// default action for all cases without special treatment:
399
unitString = quant.getUnit().getString();
403
return toLocale(quant, factor, unitString);