| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include<cmath> |
| | #include<iostream> |
| | #include<limits> |
| |
|
| | #include<QObject> |
| | #include<QStringList> |
| | #include <QRegularExpression> |
| |
|
| | #include "rs_units.h" |
| |
|
| | #include "rs_debug.h" |
| | #include "rs_math.h" |
| | #include "rs_vector.h" |
| |
|
| | namespace { |
| |
|
| | |
| | |
| | |
| | |
| | |
| | bool isAbsInRange(double length) |
| | { |
| | if (std::isnan(length) || !std::isfinite(length) ) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "length=%lg", length); |
| | return false; |
| | } |
| | if (std::abs(length) > std::numeric_limits<unsigned>::max()) { |
| | RS_DEBUG->print(RS_Debug::D_ERROR, "length=%lg is too big in magnitude for the current dimension type", length); |
| | return false; |
| | } |
| | return true; |
| | } |
| | } |
| |
|
| | RS2::Unit RS_Units::currentDrawingUnits = (RS2::Unit) 0; |
| |
|
| | |
| | |
| | |
| | RS2::Unit RS_Units::dxfint2unit(int dxfint) { |
| | return (RS2::Unit)dxfint; |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | QString RS_Units::unitToSign(RS2::Unit u) { |
| | QString ret = ""; |
| |
|
| | switch (u) { |
| | case RS2::None: |
| | ret = ""; |
| | break; |
| | case RS2::Inch: |
| | ret = "\""; |
| | break; |
| | case RS2::Foot: |
| | ret = "'"; |
| | break; |
| | case RS2::Mile: |
| | ret = "mi"; |
| | break; |
| | case RS2::Millimeter: |
| | ret = "mm"; |
| | break; |
| | case RS2::Centimeter: |
| | ret = "cm"; |
| | break; |
| | case RS2::Meter: |
| | ret = "m"; |
| | break; |
| | case RS2::Kilometer: |
| | ret = "km"; |
| | break; |
| | case RS2::Microinch: |
| | ret = "µ\""; |
| | break; |
| | case RS2::Mil: |
| | ret = "mil"; |
| | break; |
| | case RS2::Yard: |
| | ret = "yd"; |
| | break; |
| | case RS2::Angstrom: |
| | ret = "A"; |
| | break; |
| | case RS2::Nanometer: |
| | ret = "nm"; |
| | break; |
| | case RS2::Micron: |
| | ret = "µm"; |
| | break; |
| | case RS2::Decimeter: |
| | ret = "dm"; |
| | break; |
| | case RS2::Decameter: |
| | ret = "dam"; |
| | break; |
| | case RS2::Hectometer: |
| | ret = "hm"; |
| | break; |
| | case RS2::Gigameter: |
| | ret = "Gm"; |
| | break; |
| | case RS2::Astro: |
| | ret = "astro"; |
| | break; |
| | case RS2::Lightyear: |
| | ret = "ly"; |
| | break; |
| | case RS2::Parsec: |
| | ret = "pc"; |
| | break; |
| |
|
| | default: |
| | ret = ""; |
| | break; |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | QString RS_Units::unitToString(RS2::Unit u, bool t) { |
| | switch (u) { |
| | case RS2::None: |
| | return t ? QObject::tr("None", "unknown length unit") : "None"; |
| | case RS2::Inch: |
| | return t ? QObject::tr("Inch") : "Inch"; |
| | case RS2::Foot: |
| | return t ? QObject::tr("Foot") : "Foot"; |
| | case RS2::Mile: |
| | return t ? QObject::tr("Mile") : "Mile"; |
| | case RS2::Millimeter: |
| | return t ? QObject::tr("Millimeter") : "Millimeter"; |
| | case RS2::Centimeter: |
| | return t ? QObject::tr("Centimeter") : "Centimeter"; |
| | case RS2::Meter: |
| | return t ? QObject::tr("Meter") : "Meter"; |
| | case RS2::Kilometer: |
| | return t ? QObject::tr("Kilometer") : "Kilometer"; |
| | case RS2::Microinch: |
| | return t ? QObject::tr("Microinch") : "Microinch"; |
| | case RS2::Mil: |
| | return t ? QObject::tr("Mil") : "Mil"; |
| | case RS2::Yard: |
| | return t ? QObject::tr("Yard") : "Yard"; |
| | case RS2::Angstrom: |
| | return t ? QObject::tr("Angstrom") : "Angstrom"; |
| | case RS2::Nanometer: |
| | return t ? QObject::tr("Nanometer") : "Nanometer"; |
| | case RS2::Micron: |
| | return t ? QObject::tr("Micron") : "Micron"; |
| | case RS2::Decimeter: |
| | return t ? QObject::tr("Decimeter") : "Decimeter"; |
| | case RS2::Decameter: |
| | return t ? QObject::tr("Decameter") : "Decameter"; |
| | case RS2::Hectometer: |
| | return t ? QObject::tr("Hectometer") : "Hectometer"; |
| | case RS2::Gigameter: |
| | return t ? QObject::tr("Gigameter") : "Gigameter"; |
| | case RS2::Astro: |
| | return t ? QObject::tr("Astro") : "Astro"; |
| | case RS2::Lightyear: |
| | return t ? QObject::tr("Lightyear") : "Lightyear"; |
| | case RS2::Parsec: |
| | return t ? QObject::tr("Parsec") : "Parsec"; |
| |
|
| | default: |
| | return ""; |
| | } |
| |
|
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | RS2::Unit RS_Units::stringToUnit(const QString& u) { |
| | RS2::Unit ret = RS2::None; |
| |
|
| | if (u=="None") { |
| | ret = RS2::None; |
| | } else if (u==QObject::tr("Inch")) { |
| | ret = RS2::Inch; |
| | } else if (u==QObject::tr("Foot")) { |
| | ret = RS2::Foot; |
| | } else if (u==QObject::tr("Mile")) { |
| | ret = RS2::Mile; |
| | } else if (u==QObject::tr("Millimeter")) { |
| | ret = RS2::Millimeter; |
| | } else if (u==QObject::tr("Centimeter")) { |
| | ret = RS2::Centimeter; |
| | } else if (u==QObject::tr("Meter")) { |
| | ret = RS2::Meter; |
| | } else if (u==QObject::tr("Kilometer")) { |
| | ret = RS2::Kilometer; |
| | } else if (u==QObject::tr("Microinch")) { |
| | ret = RS2::Microinch; |
| | } else if (u==QObject::tr("Mil")) { |
| | ret = RS2::Mil; |
| | } else if (u==QObject::tr("Yard")) { |
| | ret = RS2::Yard; |
| | } else if (u==QObject::tr("Angstrom")) { |
| | ret = RS2::Angstrom; |
| | } else if (u==QObject::tr("Nanometer")) { |
| | ret = RS2::Nanometer; |
| | } else if (u==QObject::tr("Micron")) { |
| | ret = RS2::Micron; |
| | } else if (u==QObject::tr("Decimeter")) { |
| | ret = RS2::Decimeter; |
| | } else if (u==QObject::tr("Decameter")) { |
| | ret = RS2::Decameter; |
| | } else if (u==QObject::tr("Hectometer")) { |
| | ret = RS2::Hectometer; |
| | } else if (u==QObject::tr("Gigameter")) { |
| | ret = RS2::Gigameter; |
| | } else if (u==QObject::tr("Astro")) { |
| | ret = RS2::Astro; |
| | } else if (u==QObject::tr("Lightyear")) { |
| | ret = RS2::Lightyear; |
| | } else if (u==QObject::tr("Parsec")) { |
| | ret = RS2::Parsec; |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | bool RS_Units::isMetric(RS2::Unit u) { |
| | switch (u) { |
| | case RS2::Millimeter: |
| | case RS2::Centimeter: |
| | case RS2::Meter: |
| | case RS2::Kilometer: |
| | case RS2::Angstrom: |
| | case RS2::Nanometer: |
| | case RS2::Micron: |
| | case RS2::Decimeter: |
| | case RS2::Decameter: |
| | case RS2::Hectometer: |
| | case RS2::Gigameter: |
| | case RS2::Astro: |
| | case RS2::Lightyear: |
| | case RS2::Parsec: |
| | return true; |
| | default: |
| | return false; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | double RS_Units::getFactorToMM(RS2::Unit u) { |
| | switch (u) { |
| | default: |
| | case RS2::None: |
| | case RS2::Millimeter: |
| | return 1.0; |
| | case RS2::Inch: |
| | return 25.4; |
| | case RS2::Foot: |
| | return 304.8; |
| | case RS2::Mile: |
| | return 1.609344e6; |
| | case RS2::Centimeter: |
| | return 10; |
| | case RS2::Meter: |
| | return 1e3; |
| | case RS2::Kilometer: |
| | return 1e6; |
| | case RS2::Microinch: |
| | return 2.54e-5; |
| | case RS2::Mil: |
| | return 0.0254; |
| | case RS2::Yard: |
| | return 914.4; |
| | case RS2::Angstrom: |
| | return 1e-7; |
| | case RS2::Nanometer: |
| | return 1e-6; |
| | case RS2::Micron: |
| | return 1e-3; |
| | case RS2::Decimeter: |
| | return 100.0; |
| | case RS2::Decameter: |
| | return 1e4; |
| | case RS2::Hectometer: |
| | return 1e5; |
| | case RS2::Gigameter: |
| | return 1e9; |
| | case RS2::Astro: |
| | return 1.495978707e14; |
| | case RS2::Lightyear: |
| | return 9.4607304725808e18; |
| | case RS2::Parsec: |
| | return 3.0856776e19; |
| | } |
| |
|
| | } |
| |
|
| |
|
| | |
| | double RS_Units::convert(double val) |
| | { |
| | return convert(val, RS2::Millimeter, currentDrawingUnits); |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | double RS_Units::convert(double val, RS2::Unit src, RS2::Unit dest) { |
| | if (getFactorToMM(dest)>0.0) { |
| | return (val*getFactorToMM(src))/getFactorToMM(dest); |
| | } else { |
| | RS_DEBUG->print(RS_Debug::D_WARNING, |
| | "RS_Units::convert: invalid factor"); |
| | return val; |
| | } |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | RS_Vector RS_Units::convert(const RS_Vector& val, RS2::Unit src, RS2::Unit dest) { |
| | return RS_Vector(convert(val.x, src, dest), |
| | convert(val.y, src, dest), |
| | convert(val.z, src, dest) |
| | ); |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatLinear(double length, RS2::Unit unit, |
| | RS2::LinearFormat format, |
| | int prec, bool showUnit) { |
| | QString ret; |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | switch (format) { |
| | case RS2::Scientific: |
| | ret = formatScientific(length, unit, prec, showUnit); |
| | break; |
| |
|
| | case RS2::Decimal: |
| | ret = formatDecimal(length, unit, prec, showUnit); |
| | break; |
| |
|
| | case RS2::Engineering: |
| | ret = formatEngineering(length, unit, prec, showUnit); |
| | break; |
| |
|
| | case RS2::Architectural: |
| | ret = formatArchitectural(length, unit, prec, showUnit); |
| | break; |
| |
|
| | case RS2::Fractional: |
| | ret = formatFractional(length, unit, prec, showUnit); |
| | break; |
| |
|
| | case RS2::ArchitecturalMetric: |
| | ret = formatArchitecturalMetric(length, unit, prec, showUnit); |
| | break; |
| |
|
| | default: |
| | RS_DEBUG->print(RS_Debug::D_WARNING, |
| | "RS_Units::formatLinear: Unknown format"); |
| | ret = ""; |
| | break; |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatScientific(double length, RS2::Unit unit, |
| | int prec, bool showUnit) { |
| |
|
| | QString const ret= QString("%1").arg(length,0,'E', prec); |
| | if(showUnit) |
| | return ret + unitToSign(unit); |
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatDecimal(double length, RS2::Unit unit, |
| | int prec, bool showUnit) { |
| | QString const ret=RS_Math::doubleToString(length, prec); |
| |
|
| | if(showUnit) |
| | return ret+unitToSign(unit); |
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatEngineering(double length, RS2::Unit unit, |
| | int prec, bool ) { |
| | |
| | if (!isAbsInRange(length)) |
| | return "<Invalid length>"; |
| |
|
| | unsigned feet = convert(std::abs(length), unit, RS2::Foot); |
| | double inches = convert(std::abs(length), unit, RS2::Inch) - feet * 12; |
| |
|
| | QString sInches = RS_Math::doubleToString(inches, prec); |
| |
|
| | if (sInches=="12") { |
| | feet++; |
| | sInches="0"; |
| | } |
| |
|
| | QString ret; |
| | if (feet > 0) { |
| | ret = QString(R"(%1'-%2")").arg(feet).arg(sInches); |
| | } else { |
| | ret = sInches + '"'; |
| | } |
| |
|
| | return std::signbit(length) ? "-" + ret : ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatArchitectural(double length, RS2::Unit unit, |
| | int prec, bool showUnit) { |
| | |
| | if (!isAbsInRange(length)) |
| | return "<Invalid length>"; |
| |
|
| | QString negativeSign = std::signbit(length)?"-":""; |
| |
|
| | unsigned feet = convert(std::abs(length), unit, RS2::Foot); |
| | double inches = convert(std::abs(length), unit, RS2::Inch) - feet * 12; |
| |
|
| | |
| | if (inches >= 12.) { |
| | feet++; |
| | inches -= 12.; |
| | } |
| |
|
| | QString sInches = formatFractional(inches, RS2::Inch, prec, showUnit); |
| |
|
| | |
| | if (sInches=="12") { |
| | feet++; |
| | sInches = "0"; |
| | } |
| |
|
| | if (feet != 0) { |
| | return QString(R"(%1%2'-%3")").arg(negativeSign).arg(feet).arg(sInches); |
| | } else { |
| | return QString(R"(%1")").arg(sInches); |
| | } |
| |
|
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatArchitecturalMetric(double length, RS2::Unit unit, |
| | int prec, bool showUnit) { |
| | |
| | if (!isAbsInRange(length)) |
| | return "<Invalid length>"; |
| |
|
| | QString ret = RS_Math::doubleToString(std::abs(length), prec + 1); |
| | unsigned iLast = QString(ret.right(1)).toUInt(); |
| |
|
| | |
| | if ((iLast > 2) && (iLast < 8)) { |
| | ret = ret.replace(ret.length() - 1, 1, "\u2075"); |
| | } else { |
| | ret = RS_Math::doubleToString(length, prec); |
| | } |
| |
|
| | |
| | const QChar zero = '0'; |
| | if (ret.startsWith(zero)) { |
| | auto parts = ret.split("."); |
| | if (parts.size() > 1) { |
| | ret = parts[1]; |
| | |
| | if (ret.startsWith(zero)) { |
| | ret = ret.remove(0, 1); |
| | } |
| | } |
| | } |
| | if (showUnit) { |
| | ret = QString("%1 %2").arg(ret).arg(unitToSign(unit)); |
| | } |
| | return std::signbit(length) ? "-" + ret : ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatFractional(double length, RS2::Unit , |
| | int prec, bool ) { |
| | |
| | if (!isAbsInRange(length)) |
| | return "<Invalid length>"; |
| |
|
| | |
| | if (std::signbit(length)) { |
| | QString sign = std::signbit(length + RS_TOLERANCE) ? QString{"- "} : QString{}; |
| | return sign + formatFractional(std::abs(length), RS2::Inch, prec, false); |
| | } |
| | |
| | unsigned num = (unsigned) std::abs(length); |
| |
|
| | unsigned denominator = 2<<prec; |
| | unsigned nominator = (unsigned) RS_Math::round((length-num)*denominator); |
| |
|
| | |
| | if (nominator==denominator) { |
| | nominator=0; |
| | denominator=0; |
| | ++num; |
| | } |
| |
|
| | |
| | if (nominator != 0 && denominator != 0) { |
| | unsigned gcd = RS_Math::findGCD(nominator, denominator); |
| | if (gcd) { |
| | nominator = nominator / gcd; |
| | denominator = denominator / gcd; |
| | } else { |
| | RS_DEBUG->print(RS_Debug::D_WARNING, |
| | "RS_Units::formatFractional: invalid gcd"); |
| | nominator = 0; |
| | denominator = 0; |
| | } |
| | } |
| |
|
| | |
| | QString neg = std::signbit(length) ? "-" : ""; |
| | QString ret; |
| | if (num != 0 && nominator != 0) { |
| | ret = QString("%1%2 %3/%4").arg(neg).arg(num).arg(nominator).arg(denominator); |
| | } else if(nominator != 0) { |
| | ret = QString("%1%2/%3").arg(neg).arg(nominator).arg(denominator); |
| | } else if(num != 0) { |
| | ret = QString("%1%2").arg(neg).arg(num); |
| | } else { |
| | ret = "0"; |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | QString RS_Units::formatAngle(double angle, RS2::AngleFormat format, |
| | int prec) { |
| |
|
| | QString ret; |
| | double value = std::fmod(angle, 2. * M_PI); |
| |
|
| | switch (format) { |
| | case RS2::Surveyors: |
| | case RS2::DegreesDecimal: |
| | case RS2::DegreesMinutesSeconds: |
| | value = RS_Math::rad2deg(value); |
| | break; |
| | case RS2::Gradians: |
| | value = RS_Math::rad2gra(value); |
| | break; |
| | case RS2::Radians: |
| | break; |
| | default: |
| | RS_DEBUG->print(RS_Debug::D_WARNING, |
| | "RS_Units::formatWCSAngle: Unknown Angle Unit"); |
| | return ""; |
| | break; |
| | } |
| |
|
| | switch (format) { |
| | case RS2::DegreesDecimal: |
| | case RS2::Radians: |
| | case RS2::Gradians: |
| | ret = RS_Math::doubleToString(value, prec); |
| | if (format==RS2::DegreesDecimal) |
| | ret+=QChar(0xB0); |
| | if (format==RS2::Radians) |
| | ret+="r"; |
| | if (format==RS2::Gradians) |
| | ret+="g"; |
| | break; |
| |
|
| | case RS2::DegreesMinutesSeconds: { |
| | unsigned vDegrees, vMinutes; |
| | double vSeconds; |
| | QString degrees, minutes, seconds; |
| |
|
| | vDegrees = (unsigned)std::floor(value); |
| | vMinutes = (unsigned)std::floor((value - vDegrees) * 60.0); |
| | vSeconds = (value - vDegrees - (vMinutes/60.0)) * 3600.0; |
| |
|
| | seconds = RS_Math::doubleToString(vSeconds, (prec>1 ? prec-2 : 0)); |
| |
|
| | if(seconds=="60") { |
| | seconds="0"; |
| | ++vMinutes; |
| | if(vMinutes==60) { |
| | vMinutes=0; |
| | ++vDegrees; |
| | } |
| | } |
| |
|
| | if (prec==0 && vMinutes>=30.0) { |
| | vDegrees++; |
| | } else if (prec==1 && vSeconds>=30.0) { |
| | vMinutes++; |
| | } |
| |
|
| | degrees.setNum(vDegrees); |
| | minutes.setNum(vMinutes); |
| |
|
| | switch (prec) { |
| | case 0: |
| | ret = degrees + QChar(0xB0); |
| | break; |
| | case 1: |
| | ret = degrees + QChar(0xB0) + " " + minutes + "'"; |
| | break; |
| | default: |
| | ret = degrees + QChar(0xB0) + " " + minutes + "' " |
| | + seconds + "\""; |
| | break; |
| | } |
| | } |
| | break; |
| | case RS2::Surveyors: { |
| | QString prefix,suffix; |
| | unsigned quadrant; |
| | quadrant = ((unsigned)std::floor(value)/90); |
| | switch(quadrant){ |
| | case 0: |
| | prefix="N"; |
| | suffix="E"; |
| | break; |
| | case 1: |
| | prefix="S"; |
| | suffix="E"; |
| | value=180. - value; |
| | break; |
| | case 2: |
| | prefix="S"; |
| | suffix="W"; |
| | value=value - 180.; |
| | break; |
| | case 3: |
| | prefix="N"; |
| | suffix="W"; |
| | value=360. - value; |
| | break; |
| | } |
| | ret = prefix+formatAngle(RS_Math::deg2rad(value),RS2::DegreesMinutesSeconds,prec)+suffix; |
| | ret.replace(QChar(0xB0),"d"); |
| | ret.replace(" ",""); |
| | } |
| | break; |
| | default: |
| | break; |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS2::AngleFormat RS_Units::numberToAngleFormat(int num) { |
| |
|
| | RS2::AngleFormat af; |
| |
|
| | switch (num) { |
| | default: |
| | case 0: |
| | af = RS2::DegreesDecimal; |
| | break; |
| | case 1: |
| | af = RS2::DegreesMinutesSeconds; |
| | break; |
| | case 2: |
| | af = RS2::Gradians; |
| | break; |
| | case 3: |
| | af = RS2::Radians; |
| | break; |
| | case 4: |
| | af = RS2::Surveyors; |
| | break; |
| | } |
| |
|
| | return af; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | RS_Vector RS_Units::paperFormatToSize(RS2::PaperFormat p) { |
| |
|
| | switch (p) { |
| | case RS2::Custom: |
| | return RS_Vector(0.0, 0.0); |
| |
|
| | case RS2::A0: |
| | return RS_Vector(841.0, 1189.0); |
| | case RS2::A1: |
| | return RS_Vector(594.0, 841.0); |
| | case RS2::A2: |
| | return RS_Vector(420.0, 594.0); |
| | case RS2::A3: |
| | return RS_Vector(297.0, 420.0); |
| | case RS2::A4: |
| | return RS_Vector(210.0, 297.0); |
| |
|
| | |
| |
|
| | case RS2::Letter: |
| | return RS_Vector(215.9, 279.4); |
| | case RS2::Legal: |
| | return RS_Vector(215.9, 355.6); |
| | case RS2::Tabloid: |
| | return RS_Vector(279.4, 431.8); |
| |
|
| | |
| | |
| | |
| | |
| | case RS2::Ansi_C: |
| | return RS_Vector(431.8, 558.8); |
| | case RS2::Ansi_D: |
| | return RS_Vector(558.8, 863.6); |
| | case RS2::Ansi_E: |
| | return RS_Vector(863.6, 1117.6); |
| |
|
| | case RS2::Arch_A: |
| | return RS_Vector(228.6, 304.8); |
| | case RS2::Arch_B: |
| | return RS_Vector(304.8, 457.2); |
| | case RS2::Arch_C: |
| | return RS_Vector(457.2, 609.6); |
| | case RS2::Arch_D: |
| | return RS_Vector(609.6, 914.4); |
| | case RS2::Arch_E: |
| | return RS_Vector(914.4, 1219.2); |
| |
|
| | default: |
| | break; |
| | } |
| |
|
| | return RS_Vector (false); |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | RS2::PaperFormat RS_Units::paperSizeToFormat(const RS_Vector& s) { |
| | RS_Vector ts1; |
| | RS_Vector ts2; |
| |
|
| | for (RS2::PaperFormat i = RS2::FirstPaperFormat; RS2::NPageFormat > i; i = static_cast<RS2::PaperFormat>(i + 1)) { |
| | ts1 = RS_Units::paperFormatToSize(i); |
| | ts2 = RS_Vector(ts1.y, ts1.x); |
| |
|
| | if (ts1.distanceTo(s) < 1.0e-4 || ts2.distanceTo(s) < 1.0e-4) { |
| | return i; |
| | } |
| | } |
| |
|
| | return RS2::Custom; |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | QString RS_Units::paperFormatToString(RS2::PaperFormat p) { |
| |
|
| | switch (p) { |
| | case RS2::Custom: return QObject::tr( "Custom", "Paper format"); |
| |
|
| | case RS2::A0: return QObject::tr( "A0", "Paper format"); |
| | case RS2::A1: return QObject::tr( "A1", "Paper format"); |
| | case RS2::A2: return QObject::tr( "A2", "Paper format"); |
| | case RS2::A3: return QObject::tr( "A3", "Paper format"); |
| | case RS2::A4: return QObject::tr( "A4", "Paper format"); |
| |
|
| | |
| |
|
| | case RS2::Letter: return QObject::tr( "Letter / ANSI A", "Paper format"); |
| | case RS2::Legal: return QObject::tr( "Legal", "Paper format"); |
| | case RS2::Tabloid: return QObject::tr( "Tabloid / ANSI B", "Paper format"); |
| |
|
| | |
| | |
| | case RS2::Ansi_C: return QObject::tr( "ANSI C", "Paper format"); |
| | case RS2::Ansi_D: return QObject::tr( "ANSI D", "Paper format"); |
| | case RS2::Ansi_E: return QObject::tr( "ANSI E", "Paper format"); |
| |
|
| | case RS2::Arch_A: return QObject::tr( "Arch A", "Paper format"); |
| | case RS2::Arch_B: return QObject::tr( "Arch B", "Paper format"); |
| | case RS2::Arch_C: return QObject::tr( "Arch C", "Paper format"); |
| | case RS2::Arch_D: return QObject::tr( "Arch D", "Paper format"); |
| | case RS2::Arch_E: return QObject::tr( "Arch E", "Paper format"); |
| |
|
| | default: |
| | break; |
| | } |
| |
|
| | return QStringLiteral(""); |
| | } |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | RS2::PaperFormat RS_Units::stringToPaperFormat(const QString& p) { |
| | QString ls {p.toLower()}; |
| |
|
| | |
| | if (ls == QStringLiteral("custom") || ls == QObject::tr("custom", "Paper format").toLower()) |
| | return RS2::Custom; |
| |
|
| | if (ls == QStringLiteral("a0") || ls == QObject::tr("a0", "Paper format").toLower()) |
| | return RS2::A0; |
| | if (ls == QStringLiteral("a1") || ls == QObject::tr("a1", "Paper format").toLower()) |
| | return RS2::A1; |
| | if (ls == QStringLiteral("a2") || ls == QObject::tr("a2", "Paper format").toLower()) |
| | return RS2::A2; |
| | if (ls == QStringLiteral("a3") || ls == QObject::tr("a3", "Paper format").toLower()) |
| | return RS2::A3; |
| | if (ls == QStringLiteral("a4") || ls == QObject::tr("a4", "Paper format").toLower()) |
| | return RS2::A4; |
| |
|
| | |
| |
|
| | if (ls == QStringLiteral("letter") || ls == QObject::tr("letter", "Paper format").toLower()) |
| | return RS2::Letter; |
| | if (ls == QStringLiteral("legal") || ls == QObject::tr("legal", "Paper format").toLower()) |
| | return RS2::Legal; |
| | if (ls == QStringLiteral("tabloid") || ls == QObject::tr("tabloid", "Paper format").toLower()) |
| | return RS2::Tabloid; |
| |
|
| | |
| | |
| | |
| | |
| | if (ls == QStringLiteral("ansi c") || ls == QObject::tr("ansi c", "Paper format").toLower()) |
| | return RS2::Ansi_C; |
| | if (ls == QStringLiteral("ansi d") || ls == QObject::tr("ansi d", "Paper format").toLower()) |
| | return RS2::Ansi_D; |
| | if (ls == QStringLiteral("ansi e") || ls == QObject::tr("ansi e", "Paper format").toLower()) |
| | return RS2::Ansi_E; |
| |
|
| | if (ls == QStringLiteral("arch a") || ls == QObject::tr("arch a", "Paper format").toLower()) |
| | return RS2::Arch_A; |
| | if (ls == QStringLiteral("arch b") || ls == QObject::tr("arch b", "Paper format").toLower()) |
| | return RS2::Arch_B; |
| | if (ls == QStringLiteral("arch c") || ls == QObject::tr("arch c", "Paper format").toLower()) |
| | return RS2::Arch_C; |
| | if (ls == QStringLiteral("arch d") || ls == QObject::tr("arch d", "Paper format").toLower()) |
| | return RS2::Arch_D; |
| | if (ls == QStringLiteral("arch e") || ls == QObject::tr("arch e", "Paper format").toLower()) |
| | return RS2::Arch_E; |
| |
|
| | return RS2::Custom; |
| | } |
| |
|
| | |
| | |
| | |
| | double RS_Units::dpiToScale(double dpi, RS2::Unit unit) { |
| | double scale = RS_Units::convert(1.0, RS2::Inch, unit) / dpi; |
| | return scale; |
| | } |
| |
|
| | |
| | |
| | |
| | double RS_Units::scaleToDpi(double scale, RS2::Unit unit) { |
| | double dpi = RS_Units::convert(1.0, RS2::Inch, unit) / scale; |
| | return dpi; |
| | } |
| |
|
| | namespace{ |
| | static QRegularExpression surveyorRegExp = QRegularExpression( |
| | "\\b" |
| | "(?:" |
| | "(?:" |
| | "([NS])" |
| | "(?:" |
| | "([+-]?)" |
| | "(?:" |
| | "(?:(\\d*\\.?\\d*)[d°])?" |
| | "(?:(\\d*\\.?\\d*)')?" |
| | "(?:(\\d*\\.?\\d*)\")?" |
| | "|" |
| | "(\\d*)" |
| | ")" |
| | "([EW])" |
| | ")?" |
| | ")" |
| | "|" |
| | "([EW])" |
| | ")" |
| | "\\b", |
| | QRegularExpression::CaseInsensitiveOption |
| | ); |
| |
|
| | static QRegularExpression surveyorQuickCheckRegExp = QRegularExpression("[NESW]", QRegularExpression::CaseInsensitiveOption); |
| |
|
| | static QRegularExpression radiantRegExp = QRegularExpression("((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))r\\b", QRegularExpression::CaseInsensitiveOption); |
| |
|
| | static QRegularExpression gradRegExp = QRegularExpression("((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))g\\b", QRegularExpression::CaseInsensitiveOption); |
| |
|
| | static QRegularExpression explicitDegreesRegExp = QRegularExpression( |
| | "(?:[^a-zA-Z0-9]|^)" |
| | "(" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))[d°])" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))')?" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))\")?" |
| | ")" |
| | "(?:[^\\d]|$)", |
| | QRegularExpression::CaseInsensitiveOption); |
| |
|
| | static QRegularExpression explicitBearingRexExp = QRegularExpression( |
| | "(?:[^a-zA-Z0-9]|^)" |
| | "(" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))b)" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))')?" |
| | "(?:((?:\\.\\d+)|(?:\\d+\\.\\d*)|(?:\\d+))\")?" |
| | ")" |
| | "(?:[^\\d]|$)", |
| | QRegularExpression::CaseInsensitiveOption); |
| | } |
| |
|
| | QString RS_Units::replaceSurveyorsAnglesByDecimalDegrees(QString val, bool *ok, QString& errorMsg){ |
| | int idx = -1; |
| | QString expr = val; |
| | |
| | if (expr.contains(surveyorQuickCheckRegExp)) { |
| | QRegularExpressionMatch match; |
| | do { |
| | idx = (int)expr.indexOf(surveyorRegExp, 0, &match); |
| |
|
| | if (idx==-1) { |
| | break; |
| | } |
| | double angle = 0.0; |
| | QString sign; |
| |
|
| | |
| | const QString &group8 = match.captured(8).toUpper(); |
| | if (!group8.isEmpty()) { |
| | if (group8 == "E") { |
| | angle = 0.0; |
| | } |
| | else if (group8 == "W") { |
| | angle = 180.0; |
| | } |
| | else { |
| | if (ok != nullptr) { |
| | *ok = false; |
| | } |
| | |
| | errorMsg = "Uxexpected cardinal direction for surveyor angle candidate (valid values are: N,E,S,W)"; |
| | return ""; |
| | } |
| | } |
| | |
| | else { |
| | const QString &group1 = match.captured(1).toUpper(); |
| | bool north = group1 == "N"; |
| | bool south = group1 == "S"; |
| | sign = match.captured(2); |
| | double degrees = 0.0; |
| | double minutes = 0.0; |
| | double seconds = 0.0; |
| | if (!match.captured(6).isEmpty()) { |
| | degrees = match.captured(6).toDouble(ok); |
| | } |
| | else { |
| | const QString &strDegrees = match.captured(3); |
| | const QString &strMinutes = match.captured(4); |
| | const QString &strSeconds = match.captured(5); |
| | degrees = strDegrees.toDouble(ok); |
| | minutes = strMinutes.toDouble(ok); |
| | seconds = strSeconds.toDouble(ok); |
| | } |
| | const QString &group7 = match.captured(7).toUpper(); |
| | bool east = group7 == "E"; |
| | bool west = group7 == "W"; |
| |
|
| | double base = (north ? 90.0 : 270.0); |
| | int dir = ((north && west) || (south && east) ? 1 : -1); |
| | angle = base + dir * (degrees + minutes/60.0 + seconds/3600.0); |
| | } |
| |
|
| | expr.replace(match.captured(0),QString("%1%2").arg(sign).arg(angle, 0, 'g', 16)); |
| | } while(idx!=-1); |
| | } |
| | return expr; |
| | } |
| |
|
| | QString RS_Units::replaceRadiantAnglesByDecimalDegrees(QString& val, bool *ok){ |
| | |
| | QString expr = val; |
| | int idx = -1; |
| | QRegularExpressionMatch match; |
| | do { |
| | idx = (int)expr.indexOf(radiantRegExp, 0,&match); |
| | if (idx==-1) { |
| | break; |
| | } |
| | QString m = match.captured(1); |
| | expr.replace(radiantRegExp, QString("%1").arg(RS_Math::rad2deg(m.toDouble(ok)), 0, 'g', 16) |
| | ); |
| | } while(idx!=-1); |
| | return expr; |
| | } |
| |
|
| | QString RS_Units::replaceGradAnglesByDecimalDegrees(QString& val, bool *ok) { |
| | |
| | QRegularExpressionMatch match; |
| | QString expr = val; |
| | int idx = -1; |
| | do { |
| | int idx = (int) expr.indexOf(gradRegExp, 0, &match); |
| | if (idx==-1) { |
| | break; |
| | } |
| | QString m = match.captured(1); |
| | expr.replace(gradRegExp, QString("%1").arg(RS_Math::gra2deg(m.toDouble(ok)), 0, 'g', 16)); |
| | } while(idx!=-1); |
| | return expr; |
| | } |
| |
|
| | QString RS_Units::replaceExplicitDegreesByDecimalDegrees(QString& val, bool *ok) { |
| | |
| | QRegularExpressionMatch match; |
| | QString expr = val; |
| | int idx = -1; |
| | do { |
| | idx = (int) expr.indexOf(explicitDegreesRegExp, 0, &match); |
| | if (idx==-1) { |
| | break; |
| | } |
| |
|
| | double degrees = 0.0; |
| | double minutes = 0.0; |
| | double seconds = 0.0; |
| | const QString &strDegrees = match.captured(2); |
| | const QString &strMinutes = match.captured(3); |
| | const QString &strSeconds = match.captured(4); |
| | degrees = strDegrees.toDouble(ok); |
| | minutes = strMinutes.toDouble(ok); |
| | seconds = strSeconds.toDouble(ok); |
| |
|
| | double angle = degrees + minutes/60.0 + seconds/3600.0; |
| |
|
| | expr.replace(match.captured(1), QString("%1").arg(angle, 0, 'g', 16)); |
| | } while(idx!=-1); |
| | return expr; |
| | } |
| |
|
| | QString RS_Units::replaceExplicitBearingAnglesByDecimalDegrees(QString& val, bool *ok) { |
| | |
| | QRegularExpressionMatch match; |
| | QString expr = val; |
| | int idx = -1; |
| | do { |
| | idx = (int) expr.indexOf(explicitBearingRexExp, 0, &match); |
| | if (idx==-1) { |
| | break; |
| | } |
| |
|
| | double degrees = 0.0; |
| | double minutes = 0.0; |
| | double seconds = 0.0; |
| | const QString &strDegrees = match.captured(2); |
| | const QString &strMinutes = match.captured(3); |
| | const QString &strSeconds = match.captured(4); |
| | degrees = strDegrees.toDouble(ok); |
| | minutes = strMinutes.toDouble(ok); |
| | seconds = strSeconds.toDouble(ok); |
| |
|
| | double angle = degrees + minutes/60.0 + seconds/3600.0; |
| | angle = 90.0 - angle; |
| | angle = fmod(angle,360.0); |
| |
|
| | expr.replace(match.captured(1),QString("%1").arg(angle, 0, 'g', 16)); |
| | } while(idx!=-1); |
| | return expr; |
| | } |
| |
|
| | QString RS_Units::replaceAllPotentialAnglesByDecimalDegrees(const QString &val, bool *ok) { |
| | QString expr = val; |
| | QString msg; |
| | bool noError; |
| | expr = replaceSurveyorsAnglesByDecimalDegrees(expr, &noError, msg); |
| | if (noError){ |
| | expr = replaceRadiantAnglesByDecimalDegrees(expr, &noError); |
| | if (noError){ |
| | expr = replaceExplicitDegreesByDecimalDegrees(expr, &noError); |
| | if (noError){ |
| | expr = replaceExplicitDegreesByDecimalDegrees(expr, &noError); |
| | } |
| | } |
| | } |
| | if (ok != nullptr){ |
| | *ok = noError; |
| | } |
| | if (noError){ |
| | return expr; |
| | } |
| | else{ |
| | return val; |
| | } |
| | } |
| |
|
| | double RS_Units::evalAngleValue(const QString &c, bool *ok){ |
| | QString normalizedString = replaceAllPotentialAnglesByDecimalDegrees(c, ok); |
| | double result = 0.0; |
| | if (ok){ |
| | result = RS_Math::eval(normalizedString, ok); |
| | } |
| | return result; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void RS_Units::test() { |
| | QString s; |
| | double v; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | for (v=11.9999; v<12.0001; v+=0.0000001) { |
| | for (int prec=0; prec<=6; ++prec) { |
| | s = RS_Units::formatLinear(v, RS2::Inch, RS2::Architectural, |
| | prec, true); |
| | |
| | std::cout << "prec: " << prec << " v: " << v << " s: " << s.toLatin1().data() << "\n"; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|