1
/****************************************************************************
3
** This file is part of the LibreCAD project, a 2D CAD program
5
** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
9
** This file may be distributed and/or modified under the terms of the
10
** GNU General Public License version 2 as published by the Free Software
11
** Foundation and appearing in the file gpl-2.0.txt included in the
12
** packaging of this file.
14
** This program is distributed in the hope that it will be useful,
15
** but WITHOUT ANY WARRANTY; without even the implied warranty of
16
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
** GNU General Public License for more details.
19
** You should have received a copy of the GNU General Public License
20
** along with this program; if not, write to the Free Software
21
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
** This copyright notice MUST APPEAR in all copies of the script!
25
**********************************************************************/
36
* Converts a DXF integer () to a Unit enum.
38
RS2::Unit RS_Units::dxfint2unit(int dxfint) {
39
return (RS2::Unit)dxfint;
52
return RS2::Millimeter;
54
return RS2::Centimeter;
58
return RS2::Kilometer;
60
return RS2::Microinch;
68
return RS2::Nanometer;
72
return RS2::Decimeter;
74
return RS2::Decameter;
76
return RS2::Hectometer;
78
return RS2::Gigameter;
82
return RS2::Lightyear;
90
* @return a short string representing the given unit (e.g. "mm")
92
QString RS_Units::unitToSign(RS2::Unit u) {
108
case RS2::Millimeter:
111
case RS2::Centimeter:
144
case RS2::Hectometer:
171
* @return a string representing the given unit (e.g. "Millimeter").
172
* translated if @a t is true (the default).
174
QString RS_Units::unitToString(RS2::Unit u, bool t) {
179
ret = t ? QObject::tr("None") : QString("None");
182
ret = t ? QObject::tr("Inch") : QString("Inch");
185
ret = t ? QObject::tr("Foot") : QString("Foot");
188
ret = t ? QObject::tr("Mile") : QString("Mile");
190
case RS2::Millimeter:
191
ret = t ? QObject::tr("Millimeter") : QString("Millimeter");
193
case RS2::Centimeter:
194
ret = t ? QObject::tr("Centimeter") : QString("Centimeter");
197
ret = t ? QObject::tr("Meter") : QString("Meter");
200
ret = t ? QObject::tr("Kilometer") : QString("Kilometer");
203
ret = t ? QObject::tr("Microinch") : QString("Microinch");
206
ret = t ? QObject::tr("Mil") : QString("Mil");
209
ret = t ? QObject::tr("Yard") : QString("Yard");
212
ret = t ? QObject::tr("Angstrom") : QString("Angstrom");
215
ret = t ? QObject::tr("Nanometer") : QString("Nanometer");
218
ret = t ? QObject::tr("Micron") : QString("Micron");
221
ret = t ? QObject::tr("Decimeter") : QString("Decimeter");
224
ret = t ? QObject::tr("Decameter") : QString("Decameter");
226
case RS2::Hectometer:
227
ret = t ? QObject::tr("Hectometer") : QString("Hectometer");
230
ret = t ? QObject::tr("Gigameter") : QString("Gigameter");
233
ret = t ? QObject::tr("Astro") : QString("Astro");
236
ret = t ? QObject::tr("Lightyear") : QString("Lightyear");
239
ret = t ? QObject::tr("Parsec") : QString("Parsec");
253
* Converts a string into a unit enum.
255
RS2::Unit RS_Units::stringToUnit(const QString& u) {
256
RS2::Unit ret = RS2::None;
260
} else if (u==QObject::tr("Inch")) {
262
} else if (u==QObject::tr("Foot")) {
264
} else if (u==QObject::tr("Mile")) {
266
} else if (u==QObject::tr("Millimeter")) {
267
ret = RS2::Millimeter;
268
} else if (u==QObject::tr("Centimeter")) {
269
ret = RS2::Centimeter;
270
} else if (u==QObject::tr("Meter")) {
272
} else if (u==QObject::tr("Kilometer")) {
273
ret = RS2::Kilometer;
274
} else if (u==QObject::tr("Microinch")) {
275
ret = RS2::Microinch;
276
} else if (u==QObject::tr("Mil")) {
278
} else if (u==QObject::tr("Yard")) {
280
} else if (u==QObject::tr("Angstrom")) {
282
} else if (u==QObject::tr("Nanometer")) {
283
ret = RS2::Nanometer;
284
} else if (u==QObject::tr("Micron")) {
286
} else if (u==QObject::tr("Decimeter")) {
287
ret = RS2::Decimeter;
288
} else if (u==QObject::tr("Decameter")) {
289
ret = RS2::Decameter;
290
} else if (u==QObject::tr("Hectometer")) {
291
ret = RS2::Hectometer;
292
} else if (u==QObject::tr("Gigameter")) {
293
ret = RS2::Gigameter;
294
} else if (u==QObject::tr("Astro")) {
296
} else if (u==QObject::tr("Lightyear")) {
297
ret = RS2::Lightyear;
298
} else if (u==QObject::tr("Parsec")) {
309
* @return true: the unit is metric, false: the unit is imperial.
311
bool RS_Units::isMetric(RS2::Unit u) {
312
if (u==RS2::Millimeter ||
313
u==RS2::Centimeter ||
321
u==RS2::Hectometer ||
336
* @return factor to convert the given unit to Millimeters.
338
double RS_Units::getFactorToMM(RS2::Unit u) {
354
case RS2::Millimeter:
357
case RS2::Centimeter:
390
case RS2::Hectometer:
397
ret = 149600000000000.0;
400
ret = 9460731798000000000.0;
403
ret = 30857000000000000000.0;
415
* Converts the given value 'val' from unit 'src' to unit 'dest'.
417
double RS_Units::convert(double val, RS2::Unit src, RS2::Unit dest) {
418
if (getFactorToMM(dest)>0.0) {
419
return (val*getFactorToMM(src))/getFactorToMM(dest);
421
RS_DEBUG->print(RS_Debug::D_WARNING,
422
"RS_Units::convert: invalid factor");
430
* Converts the given vector 'val' from unit 'src' to unit 'dest'.
432
RS_Vector RS_Units::convert(const RS_Vector val, RS2::Unit src, RS2::Unit dest) {
433
return RS_Vector(convert(val.x, src, dest),
434
convert(val.y, src, dest)
436
, convert(val.z, src, dest)
444
* Formats the given length in the given format.
446
* @param length The length in the current unit of the drawing.
447
* @param format Format of the string.
448
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
449
& @param showUnit Append unit to the value.
451
QString RS_Units::formatLinear(double length, RS2::Unit unit,
452
RS2::LinearFormat format,
453
int prec, bool showUnit) {
456
// unit appended to value (e.g. 'mm'):
457
/*QString unitString = "";
459
unitString = unitToSign(unit);
462
// barbarian display: show as fraction:
464
case RS2::Scientific:
465
ret = formatScientific(length, unit, prec, showUnit);
469
ret = formatDecimal(length, unit, prec, showUnit);
472
case RS2::Engineering:
473
ret = formatEngineering(length, unit, prec, showUnit);
476
case RS2::Architectural:
477
ret = formatArchitectural(length, unit, prec, showUnit);
480
case RS2::Fractional:
481
ret = formatFractional(length, unit, prec, showUnit);
485
RS_DEBUG->print(RS_Debug::D_WARNING,
486
"RS_Units::formatLinear: Unknown format");
497
* Formats the given length in scientific format (e.g. 2.5E7).
499
* @param length The length in the current unit of the drawing.
500
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
501
& @param showUnit Append unit to the value.
503
QString RS_Units::formatScientific(double length, RS2::Unit unit,
504
int prec, bool showUnit) {
508
// unit appended to value (e.g. 'mm'):
509
QString unitString = "";
511
unitString = unitToSign(unit);
514
ret = QString("%1%2").arg(length,0,'E', prec).arg(unitString);
522
* Formats the given length in decimal (normal) format (e.g. 2.5).
524
* @param length The length in the current unit of the drawing.
525
* @param prec Precisision of the value (e.g. 0.001)
526
& @param showUnit Append unit to the value.
528
QString RS_Units::formatDecimal(double length, RS2::Unit unit,
529
int prec, bool showUnit) {
533
// unit appended to value (e.g. 'mm'):
534
QString unitString = "";
536
unitString = unitToSign(unit);
539
ret = RS_Math::doubleToString(length, prec);
550
* Formats the given length in engineering format (e.g. 5' 4.5").
552
* @param length The length in the current unit of the drawing.
553
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
554
& @param showUnit Append unit to the value.
556
QString RS_Units::formatEngineering(double length, RS2::Unit /*unit*/,
557
int prec, bool /*showUnit*/) {
560
bool sign = (length<0.0);
561
int feet = (int)floor(fabs(length)/12);
562
double inches = fabs(length) - feet*12;
564
QString sInches = RS_Math::doubleToString(inches, prec);
572
ret = QString("%1'-%2\"").arg(feet).arg(sInches);
574
ret = QString("%1\"").arg(sInches);
587
* Formats the given length in architectural format (e.g. 5' 4 1/2").
589
* @param length The length in the current unit of the drawing.
590
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
591
& @param showUnit Append unit to the value.
593
QString RS_Units::formatArchitectural(double length, RS2::Unit /*unit*/,
594
int prec, bool showUnit) {
596
bool neg = (length<0.0);
598
int feet = (int)floor(fabs(length)/12);
599
double inches = fabs(length) - feet*12;
601
QString sInches = formatFractional(inches, RS2::Inch, prec, showUnit);
609
ret = QString("-%1'-%2\"").arg(feet).arg(sInches);
611
ret = QString("%1'-%2\"").arg(feet).arg(sInches);
620
* Formats the given length in fractional (barbarian) format (e.g. 5' 3 1/64").
622
* @param length The length in the current unit of the drawing.
623
* @param unit Should be inches.
624
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
625
& @param showUnit Append unit to the value.
627
QString RS_Units::formatFractional(double length, RS2::Unit /*unit*/,
628
int prec, bool /*showUnit*/) {
632
int num; // number of complete inches (num' 7/128")
633
int nominator; // number of fractions (nominator/128)
634
int denominator; // (4/denominator)
640
length = fabs(length);
643
num = (int)floor(length);
645
denominator = (int)RS_Math::pow(2, prec);
646
nominator = RS_Math::round((length-num)*denominator);
648
// fraction rounds up to 1:
649
if (nominator==denominator) {
655
// Simplify the fraction
656
if (nominator!=0 && denominator!=0) {
657
int gcd = RS_Math::findGCD(nominator, denominator);
659
nominator = nominator / gcd;
660
denominator = denominator / gcd;
662
RS_DEBUG->print(RS_Debug::D_WARNING,
663
"RS_Units::formatFractional: invalid gcd");
669
if( num!=0 && nominator!=0 ) {
670
ret = QString("%1%2 %3/%4").arg(neg).arg(num).arg(nominator).arg(denominator);
671
} else if(nominator!=0) {
672
ret = QString("%1%2/%3").arg(neg).arg(nominator).arg(denominator);
674
ret = QString("%1%2").arg(neg).arg(num);
687
* Formats the given angle with the given format.
689
* @param angle The angle (always in rad).
690
* @param format Format of the string.
691
* @param prec Precisision of the value (e.g. 0.001 or 1/128 = 0.0078125)
693
* @ret String with the formatted angle.
695
QString RS_Units::formatAngle(double angle, RS2::AngleFormat format,
702
case RS2::DegreesDecimal:
703
case RS2::DegreesMinutesSeconds:
704
value = RS_Math::rad2deg(angle);
710
value = RS_Math::rad2gra(angle);
713
RS_DEBUG->print(RS_Debug::D_WARNING,
714
"RS_Units::formatAngle: Unknown Angle Unit");
720
case RS2::DegreesDecimal:
723
ret = RS_Math::doubleToString(value, prec);
724
if (format==RS2::DegreesDecimal)
726
if (format==RS2::Radians)
728
if (format==RS2::Gradians)
732
case RS2::DegreesMinutesSeconds: {
733
int vDegrees, vMinutes;
735
QString degrees, minutes, seconds;
737
vDegrees = (int)floor(value);
738
vMinutes = (int)floor((value - vDegrees) * 60.0);
739
vSeconds = (value - vDegrees - (vMinutes/60.0)) * 3600.0;
741
seconds = RS_Math::doubleToString(vSeconds, (prec>1 ? prec-2 : 0));
752
if (prec==0 && vMinutes>=30.0) {
754
} else if (prec==1 && vSeconds>=30.0) {
758
degrees.setNum(vDegrees);
759
minutes.setNum(vMinutes);
763
ret = degrees + QChar(0xB0);
766
ret = degrees + QChar(0xB0) + " " + minutes + "'";
769
ret = degrees + QChar(0xB0) + " " + minutes + "' "
784
* Converts the given number from a DXF file into an AngleFormat enum.
786
* @param num $DIMAUNIT from DXF (0: decimal deg, 1: deg/min/sec, 2: gradians,
787
* 3: radians, 4: surveyor's units)
789
* @ret Matching AngleFormat enum value.
791
RS2::AngleFormat RS_Units::numberToAngleFormat(int num) {
798
af = RS2::DegreesDecimal;
801
af = RS2::DegreesMinutesSeconds;
819
* @return Size of the given paper format.
821
RS_Vector RS_Units::paperFormatToSize(RS2::PaperFormat p) {
822
RS_Vector ret(false);
826
ret = RS_Vector(0.0, 0.0);
829
ret = RS_Vector(215.9, 279.4);
832
ret = RS_Vector(215.9, 355.6);
835
ret = RS_Vector(190.5, 254.0);
838
ret = RS_Vector(841.0, 1189.0);
841
ret = RS_Vector(594.0, 841.0);
844
ret = RS_Vector(420.0, 594.0);
847
ret = RS_Vector(297.0, 420.0);
850
ret = RS_Vector(210.0, 297.0);
853
ret = RS_Vector(148.0, 210.0);
856
ret = RS_Vector(105.0, 148.0);
859
ret = RS_Vector(74.0, 105.0);
862
ret = RS_Vector(52.0, 74.0);
865
ret = RS_Vector(37.0, 52.0);
868
ret = RS_Vector(26.0, 37.0);
871
ret = RS_Vector(1000.0, 1414.0);
874
ret = RS_Vector(707.0, 1000.0);
877
ret = RS_Vector(500.0, 707.0);
880
ret = RS_Vector(353.0, 500.0);
883
ret = RS_Vector(250.0, 353.0);
886
ret = RS_Vector(176.0, 250.0);
889
ret = RS_Vector(125.0, 176.0);
892
ret = RS_Vector(88.0, 125.0);
895
ret = RS_Vector(62.0, 88.0);
898
ret = RS_Vector(44.0, 62.0);
901
ret = RS_Vector(31.0, 44.0);
905
ret = RS_Vector(917.0, 1297.0);
908
ret = RS_Vector(648.0, 917.0);
911
ret = RS_Vector(458.0, 648.0);
914
ret = RS_Vector(324.0, 458.0);
917
ret = RS_Vector(229.0, 324.0);
920
ret = RS_Vector(162.0, 229.0);
923
ret = RS_Vector(114.0, 162.0);
926
ret = RS_Vector(81.0, 114.0);
929
ret = RS_Vector(57.0, 81.0);
932
ret = RS_Vector(40.0, 57.0);
935
ret = RS_Vector(28.0, 40.0);
939
ret = RS_Vector(163.0, 229.0);
942
ret = RS_Vector(105.0, 241.0);
945
ret = RS_Vector(110.0, 220.0);
948
ret = RS_Vector(210.0, 330.0);
951
// ret = RS_Vector(432.0, 279.0);
954
ret = RS_Vector(279.0, 432.0);
958
return RS_Vector(229.,305.);
960
return RS_Vector(305.,457.);
962
return RS_Vector(457.,610.);
964
return RS_Vector(610.,914.);
966
return RS_Vector(914.,1219.);
968
return RS_Vector(762.,1067.);
970
return RS_Vector(660.,965.);
972
return RS_Vector(686.,991.);
975
return RS_Vector(0.0, 0.0);
987
* Gets the paper format which matches the given size. If no
988
* format matches, RS2::Custom is returned.
990
RS2::PaperFormat RS_Units::paperSizeToFormat(const RS_Vector s) {
994
for (int i=(int)RS2::Custom; i<=(int)RS2::NPageSize; ++i) {
995
ts1 = RS_Units::paperFormatToSize((RS2::PaperFormat)i);
996
ts2 = RS_Vector(ts1.y, ts1.x);
998
if (ts1.distanceTo(s)<1.0e-4 || ts2.distanceTo(s)<1.0e-4) {
999
return (RS2::PaperFormat)i;
1009
* Converts a paper format to a string (e.g. for a combobox).
1011
QString RS_Units::paperFormatToString(RS2::PaperFormat p) {
1024
case RS2::Executive:
1144
return QString("Arch A");
1146
return QString("Arch B");
1148
return QString("Arch C");
1150
return QString("Arch D");
1152
return QString("Arch E");
1154
return QString("Arch E1");
1156
return QString("Arch E2");
1158
return QString("Arch E3");
1160
case RS2::NPageSize:
1173
* Converts a string to a paper format.
1175
RS2::PaperFormat RS_Units::stringToPaperFormat(const QString& p) {
1176
QString ls = p.toLower();
1177
RS2::PaperFormat ret = RS2::Custom;
1181
} else if (p=="letter") {
1183
} else if (p=="legal") {
1185
} else if (p=="executive") {
1186
ret = RS2::Executive;
1187
} else if (p=="a0") {
1189
} else if (p=="a1") {
1191
} else if (p=="a2") {
1193
} else if (p=="a3") {
1195
} else if (p=="a4") {
1197
} else if (p=="a5") {
1199
} else if (p=="a6") {
1201
} else if (p=="a7") {
1203
} else if (p=="a8") {
1205
} else if (p=="a9") {
1207
} else if (p=="b0") {
1209
} else if (p=="b1") {
1211
} else if (p=="b2") {
1213
} else if (p=="b3") {
1215
} else if (p=="b4") {
1217
} else if (p=="b5") {
1219
} else if (p=="b6") {
1221
} else if (p=="b7") {
1223
} else if (p=="b8") {
1225
} else if (p=="b9") {
1227
} else if (p=="b10") {
1230
/*else if (p=="c0") {
1232
} else if (p=="c1") {
1234
} else if (p=="c2") {
1236
} else if (p=="c3") {
1238
} else if (p=="c4") {
1240
} else if (p=="c5") {
1242
} else if (p=="c6") {
1244
} else if (p=="c7") {
1246
} else if (p=="c8") {
1248
} else if (p=="c9") {
1250
} else if (p=="c10") {
1253
else if (p=="c5e") {
1255
} else if (p=="comm10e") {
1257
} else if (p=="dle") {
1259
} else if (p=="folio") {
1261
//} else if (p=="ledger") {
1262
// ret = RS2::Ledger;
1263
} else if (p=="tabloid") {
1266
if (p==QString("Arch A")) return RS2::Arch_A;
1267
if (p==QString("Arch B")) return RS2::Arch_B;
1268
if (p==QString("Arch C")) return RS2::Arch_C;
1269
if (p==QString("Arch D")) return RS2::Arch_D;
1270
if (p==QString("Arch E")) return RS2::Arch_E;
1271
if (p==QString("Arch E1")) return RS2::Arch_E1;
1272
if (p==QString("Arch E2")) return RS2::Arch_E2;
1273
if (p==QString("Arch E3")) return RS2::Arch_E3;
1275
if (p=="npagesize") return RS2::NPageSize;
1281
* Calculates a scaling factor from given dpi and units.
1283
double RS_Units::dpiToScale(double dpi, RS2::Unit unit) {
1284
double scale = RS_Units::convert(1.0, RS2::Inch, unit) / dpi;
1289
* Calculates a dpi value from given scaling factor and units.
1291
double RS_Units::scaleToDpi(double scale, RS2::Unit unit) {
1292
double dpi = RS_Units::convert(1.0, RS2::Inch, unit) / scale;
1297
* Performs some testing for the math class.
1299
void RS_Units::test() {
1304
std::cout << "RS_Units::test: formatLinear (decimal):\n";
1306
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1308
std::cout << "s: " << s << "\n";
1311
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1313
std::cout << "s: " << s << "\n";
1316
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1318
std::cout << "s: " << s << "\n";
1321
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1323
std::cout << "s: " << s << "\n";
1326
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1328
std::cout << "s: " << s << "\n";
1331
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1333
std::cout << "s: " << s << "\n";
1337
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Decimal,
1339
std::cout << "s: " << s << "\n";
1343
std::cout << "RS_Units::test: formatLinear (fractional):\n";
1345
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1347
std::cout << "s: " << s << "\n";
1348
assert(s=="1 13/64");
1351
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1353
std::cout << "s: " << s << "\n";
1354
assert(s=="1 51/256");
1357
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1359
std::cout << "s: " << s << "\n";
1360
assert(s=="51/256");
1363
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1365
std::cout << "s: " << s << "\n";
1369
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1371
std::cout << "s: " << s << "\n";
1375
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1377
std::cout << "s: " << s << "\n";
1381
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1383
std::cout << "s: " << s << "\n";
1387
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1389
std::cout << "s: " << s << "\n";
1393
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Fractional,
1395
std::cout << "s: " << s << "\n";
1399
for (v=11.9999; v<12.0001; v+=0.0000001) {
1400
for (int prec=0; prec<=6; ++prec) {
1401
s = RS_Units::formatLinear(v, RS2::Inch, RS2::Architectural,
1403
// RVT_PORT changed << s to s.ascii()
1404
std::cout << "prec: " << prec << " v: " << v << " s: " << s.toLatin1().data() << "\n";
1408
/*for (v=0.0; v<10.0; v+=0.001) {
1409
s = RS_Units::formatLinear(v, RS2::Foot, RS2::Fractional,
1411
std::cout << "v: " << v << " s: " << s << "\n";
1415
std::cout << "RS_Units::test: formatLinear (scientific):\n";
1417
s = RS_Units::formatLinear(v, RS2::Millimeter, RS2::Scientific,
1419
std::cout << "s: " << s << "\n";
1420
assert(s=="1.0e-3");
1425
std::cout << "RS_Units::test: formatAngle (deg / decimal):\n";
1427
s = RS_Units::formatAngle(v, RS2::DegreesDecimal, 2);
1428
std::cout << "s: " << s << "\n";
1432
s = RS_Units::formatAngle(v, RS2::DegreesDecimal, 2);
1433
std::cout << "s: " << s << "\n";
1437
s = RS_Units::formatAngle(v, RS2::DegreesDecimal, 2);
1438
std::cout << "s: " << s << "\n";
1441
std::cout << "RS_Units::test: formatAngle (deg / d/m/s):\n";
1444
s = RS_Units::formatAngle(v, RS2::DegreesMinutesSeconds, 1);
1445
std::cout << "s: " << s << "\n";
1446
assert(s=="1∞ 29' 42\"");
1449
s = RS_Units::formatAngle(v, RS2::DegreesMinutesSeconds, 1);
1450
std::cout << "s: " << s << "\n";
1451
assert(s=="1∞ 30' 0\"");