Files
create/src/Base/UnitsSchemaImperial1.cpp
wmayer e4435cdcba Base/App: fix warnings from code analysers:
* convert old-style-casts to explicit C++ casts where possible
* make some implicit conversions explicit
2022-03-06 23:49:30 +01:00

420 lines
16 KiB
C++

/***************************************************************************
* Copyright (c) 2009 Jürgen Riegel <FreeCAD@juergen-riegel.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <sstream>
#endif
#ifdef __GNUC__
# include <unistd.h>
#endif
#include <QString>
#include "UnitsSchemaImperial1.h"
using namespace Base;
//void UnitsSchemaImperial1::setSchemaUnits(void){
// // here you could change the constances used by the parser (defined in Quantity.cpp)
// Quantity::Inch = Quantity (25.4 ,Unit(1));
// Quantity::Foot = Quantity (304.8 ,Unit(1));
// Quantity::Thou = Quantity (0.0254 ,Unit(1));
// Quantity::Yard = Quantity (914.4 ,Unit(1));
// Quantity::Mile = Quantity (1609344.0 ,Unit(1));
//}
//
//void UnitsSchemaImperial1::resetSchemaUnits(void){
// // set units to US customary / Imperial units
// Quantity::Inch = Quantity (25.4 ,Unit(1));
// Quantity::Foot = Quantity (304.8 ,Unit(1));
// Quantity::Thou = Quantity (0.0254 ,Unit(1));
// Quantity::Yard = Quantity (914.4 ,Unit(1));
// Quantity::Mile = Quantity (1609344.0 ,Unit(1));
//}
QString UnitsSchemaImperial1::schemaTranslate(const Quantity &quant, double &factor, QString &unitString)
{
double UnitValue = std::abs(quant.getValue());
Unit unit = quant.getUnit();
// for imperial user/programmer mind; UnitValue is in internal system, that means
// mm/kg/s. And all combined units have to be calculated from there!
// now do special treatment on all cases seems necessary:
if (unit == Unit::Length) { // Length handling ============================
if (UnitValue < 0.00000254) {// smaller then 0.001 thou -> inch and scientific notation
unitString = QString::fromLatin1("in");
factor = 25.4;
}
else if(UnitValue < 2.54) { // smaller then 0.1 inch -> Thou (mil)
unitString = QString::fromLatin1("thou");
factor = 0.0254;
}
else if(UnitValue < 304.8) {
unitString = QString::fromLatin1("\"");
factor = 25.4;
}
else if(UnitValue < 914.4) {
unitString = QString::fromLatin1("\'");
factor = 304.8;
}
else if(UnitValue < 1609344.0) {
unitString = QString::fromLatin1("yd");
factor = 914.4;
}
else if(UnitValue < 1609344000.0) {
unitString = QString::fromLatin1("mi");
factor = 1609344.0;
}
else { // bigger then 1000 mi -> scientific notation
unitString = QString::fromLatin1("in");
factor = 25.4;
}
}
else if (unit == Unit::Angle) {
unitString = QString::fromUtf8("\xC2\xB0");
factor = 1.0;
}
else if (unit == Unit::Area) {
// TODO Cascade for the Areas
// default action for all cases without special treatment:
unitString = QString::fromLatin1("in^2");
factor = 645.16;
}
else if (unit == Unit::Volume) {
// TODO Cascade for the Volume
// default action for all cases without special treatment:
unitString = QString::fromLatin1("in^3");
factor = 16387.064;
}
else if (unit == Unit::Mass) {
// TODO Cascade for the weights
// default action for all cases without special treatment:
unitString = QString::fromLatin1("lb");
factor = 0.45359237;
}
else if (unit == Unit::Pressure) {
if (UnitValue < 6894.744) {// psi is the smallest
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
else if (UnitValue < 6894744.825) {
unitString = QString::fromLatin1("ksi");
factor = 6894.744825494;
}
else { // bigger then 1000 ksi -> psi + scientific notation
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
}
else if (unit == Unit::Stiffness) { // Conversion to lbf/in
unitString = QString::fromLatin1("lbf/in");
factor = 4.448222/0.0254;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("in/min");
factor = 25.4/60;
}
else {
// default action for all cases without special treatment:
unitString = quant.getUnit().getString();
factor = 1.0;
}
return toLocale(quant, factor, unitString);
}
QString UnitsSchemaImperialDecimal::schemaTranslate(const Base::Quantity& quant, double &factor, QString &unitString)
{
//double UnitValue = std::abs(quant.getValue());
Unit unit = quant.getUnit();
// for imperial user/programmer mind; UnitValue is in internal system, that means
// mm/kg/s. And all combined units have to be calculated from there!
// now do special treatment on all cases seems necessary:
if (unit == Unit::Length) { // Length handling ============================
unitString = QString::fromLatin1("in");
factor = 25.4;
}
else if (unit == Unit::Angle) {
unitString = QString::fromUtf8("\xC2\xB0");
factor = 1.0;
}
else if (unit == Unit::Area) {
// TODO Cascade for the Areas
// default action for all cases without special treatment:
unitString = QString::fromLatin1("in^2");
factor = 645.16;
}
else if (unit == Unit::Volume) {
// TODO Cascade for the Volume
// default action for all cases without special treatment:
unitString = QString::fromLatin1("in^3");
factor = 16387.064;
}
else if (unit == Unit::Mass) {
// TODO Cascade for the weights
// default action for all cases without special treatment:
unitString = QString::fromLatin1("lb");
factor = 0.45359237;
}
else if (unit == Unit::Pressure) {
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
else if (unit == Unit::Stiffness) {
unitString = QString::fromLatin1("lbf/in");
factor = 4.448222/0.0254;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("in/min");
factor = 25.4 / 60;
}
else if (unit == Unit::Acceleration) {
unitString = QString::fromLatin1("in/min^2");
factor = 25.4 / 3600;
}
else {
// default action for all cases without special treatment:
unitString = quant.getUnit().getString();
factor = 1.0;
}
return toLocale(quant, factor, unitString);
}
QString UnitsSchemaImperialBuilding::schemaTranslate(const Quantity &quant, double &factor, QString &unitString)
{
// this schema expresses distances in feet + inches + fractions
// ex: 3'- 4 1/4" with proper rounding
Unit unit = quant.getUnit();
if (unit == Unit::Length) {
unitString = QString::fromLatin1("in");
factor = 25.4;
// Total number of inches to format
double totalInches = std::abs(quant.getValue())/factor;
// minimum denominator (8 for 1/8, 16 for 1/16, etc)
int minden;
// Outputs
int feet; // whole feet
int inches; // whole inches
int num,den; // numerator and denominator of fractional val
std::stringstream output; // output stream
// Intermediate values
int ntot; // total fractional units
int a,b,d; // used to compute greatest common denominator
int tmp; // temporary variable for GCD
// Get the current user specified minimum denominator
minden = quant.getFormat().getDenominator();
// Compute and round the total number of fractional units
ntot = static_cast<int>(std::round(totalInches * static_cast<double>(minden)));
// If this is zero, nothing to do but return
if( ntot==0 )
return QString::fromLatin1("0");
// Compute the whole number of feet and remaining units
feet = static_cast<int>(std::floor(ntot / (12*minden)));
ntot = ntot - 12*minden*feet;
// Compute the remaining number of whole inches
inches = static_cast<int>(std::floor(ntot/minden));
// Lastly the fractional quantities
num = ntot - inches*minden;
den = minden;
// If numerator is not zero, compute greatest common divisor and reduce
// fraction
if( num!=0 )
{
// initialize
a = num;
b = den;
while (b != 0)
{
tmp = a % b;
a = b;
b = tmp;
}
d = a;
num /= d;
den /= d;
}
// Process into string. Start with negative sign if quantity is less
// than zero
if( quant.getValue() < 0 )
output << "-";
// Print feet if we have any
if( feet!=0 )
{
output << feet << "'";
// if there is to be trailing numbers, add space
if( inches!=0 || num!=0 )
{
output << " ";
}
}
// Three cases:
// 1. Whole inches, no fraction
// 2. Whole inches, fraction
// 3. Fraction only
if( inches>0 && num==0 ) // case 1.
{
output << inches << "\"";
}
else if( inches>0 && num!=0 ) // case 2
{
output << inches << "+" << num << "/" << den << "\"";
}
else if( inches==0 && num!=0 ) // case 3
{
output << num << "/" << den << "\"";
}
// Done!
return QString::fromLatin1(output.str().c_str());
}
else if (unit == Unit::Angle) {
unitString = QString::fromUtf8("\xC2\xB0");
factor = 1.0;
}
else if (unit == Unit::Area) {
unitString = QString::fromLatin1("sqft");
factor = 92903.04;
}
else if (unit == Unit::Volume) {
unitString = QString::fromLatin1("cft");
factor = 28316846.592;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("in/min");
factor = 25.4/60;
}
else {
unitString = quant.getUnit().getString();
factor = 1.0;
}
return toLocale(quant, factor, unitString);
}
QString UnitsSchemaImperialCivil::schemaTranslate(const Base::Quantity& quant, double &factor, QString &unitString)
{
// double UnitValue = std::abs(quant.getValue());
Unit unit = quant.getUnit();
// for imperial user/programmer mind; UnitValue is in internal system, that means
// mm/kg/s. And all combined units have to be calculated from there!
// now do special treatment on all cases seems necessary:
if (unit == Unit::Length) { // Length handling ============================
unitString = QString::fromLatin1("ft"); //always ft
factor = 304.8; //12 * 25.4
}
else if (unit == Unit::Area) {
unitString = QString::fromLatin1("ft^2"); //always sq.ft
factor = 92903.04;
}
else if (unit == Unit::Volume) {
unitString = QString::fromLatin1("ft^3"); //always cu. ft
factor = 28316846.592;
}
else if (unit == Unit::Mass) {
unitString = QString::fromLatin1("lb"); //always lbs.
factor = 0.45359237;
}
else if (unit == Unit::Pressure) {
unitString = QString::fromLatin1("psi");
factor = 6.894744825494;
}
else if (unit == Unit::Stiffness) {
unitString = QString::fromLatin1("lbf/in");
factor = 4.448222/0.0254;
}
else if (unit == Unit::Velocity) {
unitString = QString::fromLatin1("mph");
factor = 447.04; //1mm/sec => mph
}
// this schema expresses angles in degrees + minutes + seconds
else if (unit == Unit::Angle) {
unitString = QString::fromUtf8("deg");
QString degreeString = QString::fromUtf8("\xC2\xB0"); //degree symbol
QString minuteString = QString::fromUtf8("\xE2\x80\xB2"); //prime symbol
QString secondString = QString::fromUtf8("\xE2\x80\xB3"); //double prime symbol
factor = 1.0; //1deg = 1"\xC2\xB0 "
double totalDegrees = quant.getValue()/factor;
double wholeDegrees = std::floor(totalDegrees);
double sumMinutes = totalDegrees * 60.0; //quant as minutes
double rawMinutes = sumMinutes - wholeDegrees * 60.0;
double wholeMinutes = std::floor(rawMinutes);
double sumSeconds = totalDegrees * 3600.0; //quant as seconds
double rawSeconds = sumSeconds - (wholeDegrees * 3600.0) - (wholeMinutes * 60);
// double wholeSeconds = std::floor(rawSeconds);
// double remainSeconds = rawSeconds - wholeSeconds;
int outDeg = static_cast<int>(wholeDegrees);
int outMin = static_cast<int>(wholeMinutes);
int outSec = static_cast<int>(std::round(rawSeconds));
std::stringstream output;
output << outDeg << degreeString.toUtf8().constData();
if ((outMin > 0) || (outSec > 0)) {
output << outMin << minuteString.toUtf8().constData();
}
if (outSec > 0) {
output << outSec << secondString.toUtf8().constData();
}
// uncomment this for decimals on seconds
// if (remainSeconds < (1.0 * pow(10.0,-Base::UnitsApi::getDecimals())) ) {
// //NOP too small to display
// } else {
// output << std::setprecision(Base::UnitsApi::getDecimals()) << std::fixed <<
// rawSeconds << secondString.toStdString();
// }
return QString::fromUtf8(output.str().c_str());
}
else {
// default action for all cases without special treatment:
unitString = quant.getUnit().getString();
factor = 1.0;
}
return toLocale(quant, factor, unitString);
}