1 /*******************************************************************************
2  *  Project: libopencad
3  *  Purpose: OpenSource CAD formats support library
4  *  Author: Alexandr Borzykh, mush3d at gmail.com
5  *  Author: Dmitry Baryshnikov, bishop.dev@gmail.com
6  *  Language: C++
7  *******************************************************************************
8  *  The MIT License (MIT)
9  *
10  *  Copyright (c) 2016 Alexandr Borzykh
11  *  Copyright (c) 2016 NextGIS, <info@nextgis.com>
12  *
13  *  Permission is hereby granted, free of charge, to any person obtaining a copy
14  *  of this software and associated documentation files (the "Software"), to deal
15  *  in the Software without restriction, including without limitation the rights
16  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  *  copies of the Software, and to permit persons to whom the Software is
18  *  furnished to do so, subject to the following conditions:
19  *
20  *  The above copyright notice and this permission notice shall be included in all
21  *  copies or substantial portions of the Software.
22  *
23  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  *  SOFTWARE.
30  *******************************************************************************/
31 
32 #include "cpl_port.h"
33 #include "cpl_safemaths.hpp"
34 #include "cadheader.h"
35 #include "opencad_api.h"
36 #include "dwg/io.h"
37 
38 #include <cstring>
39 #include <iostream>
40 #include <time.h>
41 
42 #if ((defined(__sun__) || defined(__FreeBSD__)) && __GNUC__ == 4 && __GNUC_MINOR__ == 8) || defined(__ANDROID__)
43 // gcc 4.8 on Solaris 11.3 or FreeBSD 11 doesn't have std::string
44 #include <sstream>
to_string(T val)45 template <typename T> std::string to_string(T val)
46 {
47     std::ostringstream os;
48     os << val;
49     return os.str();
50 }
51 #endif
52 
53 using namespace std;
54 
55 typedef struct
56 {
57     short      nConstant;
58     short      nGroupCode;
59     const char * pszValueName;
60 } CADHeaderConstantDetail;
61 
62 #define FillCADConstantDetail( x, y ) {CADHeader::x, y, "$"#x}
63 
64 static const CADHeaderConstantDetail CADHeaderConstantDetails[]{
65         FillCADConstantDetail( OPENCADVER, 777),
66         FillCADConstantDetail( ACADMAINTVER, 70 ), FillCADConstantDetail( ACADVER, 1 ),
67         FillCADConstantDetail( ANGBASE, 50 ), FillCADConstantDetail( ANGDIR, 70 ), FillCADConstantDetail( ATTMODE, 70 ),
68         FillCADConstantDetail( AUNITS, 70 ), FillCADConstantDetail( AUPREC, 70 ), FillCADConstantDetail( CECOLOR, 62 ),
69         FillCADConstantDetail( CELTSCALE, 40 ), FillCADConstantDetail( CELTYPE, 6 ),
70         FillCADConstantDetail( CELWEIGHT, 370 ), FillCADConstantDetail( CEPSNID, 390 ),
71         FillCADConstantDetail( CEPSNTYPE, 380 ), FillCADConstantDetail( CHAMFERA, 40 ),
72         FillCADConstantDetail( CHAMFERB, 40 ), FillCADConstantDetail( CHAMFERC, 40 ),
73         FillCADConstantDetail( CHAMFERD, 40 ), FillCADConstantDetail( CLAYER, 8 ), FillCADConstantDetail( CMLJUST, 70 ),
74         FillCADConstantDetail( CMLSCALE, 40 ), FillCADConstantDetail( CMLSTYLE, 2 ),
75         FillCADConstantDetail( CSHADOW, 280 ), FillCADConstantDetail( DIMADEC, 70 ),
76         FillCADConstantDetail( DIMALT, 70 ), FillCADConstantDetail( DIMALTD, 70 ), FillCADConstantDetail( DIMALTF, 40 ),
77         FillCADConstantDetail( DIMALTRND, 40 ), FillCADConstantDetail( DIMALTTD, 70 ),
78         FillCADConstantDetail( DIMALTTZ, 70 ), FillCADConstantDetail( DIMALTU, 70 ),
79         FillCADConstantDetail( DIMALTZ, 70 ), FillCADConstantDetail( DIMAPOST, 1 ), FillCADConstantDetail( DIMASO, 70 ),
80         FillCADConstantDetail( DIMASSOC, 280 ), FillCADConstantDetail( DIMASZ, 40 ),
81         FillCADConstantDetail( DIMATFIT, 70 ), FillCADConstantDetail( DIMAUNIT, 70 ),
82         FillCADConstantDetail( DIMAZIN, 70 ), FillCADConstantDetail( DIMBLK, 1 ), FillCADConstantDetail( DIMBLK1, 1 ),
83         FillCADConstantDetail( DIMBLK2, 1 ), FillCADConstantDetail( DIMCEN, 40 ), FillCADConstantDetail( DIMCLRD, 70 ),
84         FillCADConstantDetail( DIMCLRE, 70 ), FillCADConstantDetail( DIMCLRT, 70 ), FillCADConstantDetail( DIMDEC, 70 ),
85         FillCADConstantDetail( DIMDLE, 40 ), FillCADConstantDetail( DIMDLI, 40 ), FillCADConstantDetail( DIMDSEP, 70 ),
86         FillCADConstantDetail( DIMEXE, 40 ), FillCADConstantDetail( DIMEXO, 40 ), FillCADConstantDetail( DIMFAC, 40 ),
87         FillCADConstantDetail( DIMGAP, 40 ), FillCADConstantDetail( DIMJUST, 70 ),
88         FillCADConstantDetail( DIMLDRBLK, 1 ), FillCADConstantDetail( DIMLFAC, 40 ),
89         FillCADConstantDetail( DIMLIM, 70 ), FillCADConstantDetail( DIMLUNIT, 70 ), FillCADConstantDetail( DIMLWD, 70 ),
90         FillCADConstantDetail( DIMLWE, 70 ), FillCADConstantDetail( DIMPOST, 1 ), FillCADConstantDetail( DIMRND, 40 ),
91         FillCADConstantDetail( DIMSAH, 70 ), FillCADConstantDetail( DIMSCALE, 40 ), FillCADConstantDetail( DIMSD1, 70 ),
92         FillCADConstantDetail( DIMSD2, 70 ), FillCADConstantDetail( DIMSE1, 70 ), FillCADConstantDetail( DIMSE2, 70 ),
93         FillCADConstantDetail( DIMSHO, 70 ), FillCADConstantDetail( DIMSOXD, 70 ), FillCADConstantDetail( DIMSTYLE, 2 ),
94         FillCADConstantDetail( DIMTAD, 70 ), FillCADConstantDetail( DIMTDEC, 70 ), FillCADConstantDetail( DIMTFAC, 40 ),
95         FillCADConstantDetail( DIMTIH, 70 ), FillCADConstantDetail( DIMTIX, 70 ), FillCADConstantDetail( DIMTM, 40 ),
96         FillCADConstantDetail( DIMTMOVE, 70 ), FillCADConstantDetail( DIMTOFL, 70 ),
97         FillCADConstantDetail( DIMTOH, 70 ), FillCADConstantDetail( DIMTOL, 70 ), FillCADConstantDetail( DIMTOLJ, 70 ),
98         FillCADConstantDetail( DIMTP, 40 ), FillCADConstantDetail( DIMTSZ, 40 ), FillCADConstantDetail( DIMTVP, 40 ),
99         FillCADConstantDetail( DIMTXSTY, 7 ), FillCADConstantDetail( DIMTXT, 40 ), FillCADConstantDetail( DIMTZIN, 70 ),
100         FillCADConstantDetail( DIMUPT, 70 ), FillCADConstantDetail( DIMZIN, 70 ), FillCADConstantDetail( DISPSILH, 70 ),
101         FillCADConstantDetail( DRAGVS, 349 ), FillCADConstantDetail( DWGCODEPAGE, 3 ),
102         FillCADConstantDetail( ELEVATION, 40 ), FillCADConstantDetail( ENDCAPS, 280 ),
103         FillCADConstantDetail( EXTMAX, 123 ), FillCADConstantDetail( EXTMIN, 123 ),
104         FillCADConstantDetail( EXTNAMES, 290 ), FillCADConstantDetail( FILLETRAD, 40 ),
105         FillCADConstantDetail( FILLMODE, 70 ), FillCADConstantDetail( FINGERPRINTGUID, 2 ),
106         FillCADConstantDetail( HALOGAP, 280 ), FillCADConstantDetail( HANDSEED, 5 ),
107         FillCADConstantDetail( HIDETEXT, 290 ), FillCADConstantDetail( HYPERLINKBASE, 1 ),
108         FillCADConstantDetail( INDEXCTL, 280 ), FillCADConstantDetail( INSBASE, 123 ),
109         FillCADConstantDetail( INSUNITS, 70 ), FillCADConstantDetail( INTERFERECOLOR, 62 ),
110         FillCADConstantDetail( INTERFEREOBJVS, 345 ), FillCADConstantDetail( INTERFEREVPVS, 346 ),
111         FillCADConstantDetail( INTERSECTIONCOLOR, 70 ), FillCADConstantDetail( INTERSECTIONDISPLAY, 290 ),
112         FillCADConstantDetail( JOINSTYLE, 280 ), FillCADConstantDetail( LIMCHECK, 70 ),
113         FillCADConstantDetail( LIMMAX, 1020 ), FillCADConstantDetail( LIMMIN, 1020 ),
114         FillCADConstantDetail( LTSCALE, 40 ), FillCADConstantDetail( LUNITS, 70 ), FillCADConstantDetail( LUPREC, 70 ),
115         FillCADConstantDetail( LWDISPLAY, 290 ), FillCADConstantDetail( MAXACTVP, 70 ),
116         FillCADConstantDetail( MEASUREMENT, 70 ), FillCADConstantDetail( MENU, 1 ),
117         FillCADConstantDetail( MIRRTEXT, 70 ), FillCADConstantDetail( OBSCOLOR, 70 ),
118         FillCADConstantDetail( OBSLTYPE, 280 ), FillCADConstantDetail( ORTHOMODE, 70 ),
119         FillCADConstantDetail( PDMODE, 70 ), FillCADConstantDetail( PDSIZE, 40 ),
120         FillCADConstantDetail( PELEVATION, 40 ), FillCADConstantDetail( PEXTMAX, 123 ),
121         FillCADConstantDetail( PEXTMIN, 123 ), FillCADConstantDetail( PINSBASE, 123 ),
122         FillCADConstantDetail( PLIMCHECK, 70 ), FillCADConstantDetail( PLIMMAX, 1020 ),
123         FillCADConstantDetail( PLIMMIN, 1020 ), FillCADConstantDetail( PLINEGEN, 70 ),
124         FillCADConstantDetail( PLINEWID, 40 ), FillCADConstantDetail( PROJECTNAME, 1 ),
125         FillCADConstantDetail( PROXYGRAPHICS, 70 ), FillCADConstantDetail( PSLTSCALE, 70 ),
126         FillCADConstantDetail( PSTYLEMODE, 290 ), FillCADConstantDetail( PSVPSCALE, 40 ),
127         FillCADConstantDetail( PUCSBASE, 2 ), FillCADConstantDetail( PUCSNAME, 2 ),
128         FillCADConstantDetail( PUCSORG, 123 ), FillCADConstantDetail( PUCSORGBACK, 123 ),
129         FillCADConstantDetail( PUCSORGBOTTOM, 123 ), FillCADConstantDetail( PUCSORGFRONT, 123 ),
130         FillCADConstantDetail( PUCSORGLEFT, 123 ), FillCADConstantDetail( PUCSORGRIGHT, 123 ),
131         FillCADConstantDetail( PUCSORGTOP, 123 ), FillCADConstantDetail( PUCSORTHOREF, 2 ),
132         FillCADConstantDetail( PUCSORTHOVIEW, 70 ), FillCADConstantDetail( PUCSXDIR, 123 ),
133         FillCADConstantDetail( PUCSYDIR, 123 ), FillCADConstantDetail( QTEXTMODE, 70 ),
134         FillCADConstantDetail( REGENMODE, 70 ), FillCADConstantDetail( SHADEDGE, 70 ),
135         FillCADConstantDetail( SHADEDIF, 70 ), FillCADConstantDetail( SHADOWPLANELOCATION, 40 ),
136         FillCADConstantDetail( SKETCHINC, 40 ), FillCADConstantDetail( SKPOLY, 70 ),
137         FillCADConstantDetail( SORTENTS, 280 ), FillCADConstantDetail( SPLINESEGS, 70 ),
138         FillCADConstantDetail( SPLINETYPE, 70 ), FillCADConstantDetail( SURFTAB1, 70 ),
139         FillCADConstantDetail( SURFTAB2, 70 ), FillCADConstantDetail( SURFTYPE, 70 ),
140         FillCADConstantDetail( SURFU, 70 ), FillCADConstantDetail( SURFV, 70 ), FillCADConstantDetail( TDCREATE, 40 ),
141         FillCADConstantDetail( TDINDWG, 40 ), FillCADConstantDetail( TDUCREATE, 40 ),
142         FillCADConstantDetail( TDUPDATE, 40 ), FillCADConstantDetail( TDUSRTIMER, 40 ),
143         FillCADConstantDetail( TDUUPDATE, 40 ), FillCADConstantDetail( TEXTSIZE, 40 ),
144         FillCADConstantDetail( TEXTSTYLE, 7 ), FillCADConstantDetail( THICKNESS, 40 ),
145         FillCADConstantDetail( TILEMODE, 70 ), FillCADConstantDetail( TRACEWID, 40 ),
146         FillCADConstantDetail( TREEDEPTH, 70 ), FillCADConstantDetail( UCSBASE, 2 ),
147         FillCADConstantDetail( UCSNAME, 2 ), FillCADConstantDetail( UCSORG, 123 ),
148         FillCADConstantDetail( UCSORGBACK, 123 ), FillCADConstantDetail( UCSORGBOTTOM, 123 ),
149         FillCADConstantDetail( UCSORGFRONT, 123 ), FillCADConstantDetail( UCSORGLEFT, 123 ),
150         FillCADConstantDetail( UCSORGRIGHT, 123 ), FillCADConstantDetail( UCSORGTOP, 123 ),
151         FillCADConstantDetail( UCSORTHOREF, 2 ), FillCADConstantDetail( UCSORTHOVIEW, 70 ),
152         FillCADConstantDetail( UCSXDIR, 123 ), FillCADConstantDetail( UCSYDIR, 123 ),
153         FillCADConstantDetail( UNITMODE, 70 ), FillCADConstantDetail( USERI1, 70 ), FillCADConstantDetail( USERI2, 70 ),
154         FillCADConstantDetail( USERI3, 70 ), FillCADConstantDetail( USERI4, 70 ), FillCADConstantDetail( USERI5, 70 ),
155         FillCADConstantDetail( USERR1, 40 ), FillCADConstantDetail( USERR2, 40 ), FillCADConstantDetail( USERR3, 40 ),
156         FillCADConstantDetail( USERR4, 40 ), FillCADConstantDetail( USERR5, 40 ), FillCADConstantDetail( USRTIMER, 70 ),
157         FillCADConstantDetail( VERSIONGUID, 2 ), FillCADConstantDetail( VISRETAIN, 70 ),
158         FillCADConstantDetail( WORLDVIEW, 70 ), FillCADConstantDetail( XCLIPFRAME, 290 ),
159         FillCADConstantDetail( XEDIT, 290 ), { -1, -1, nullptr }
160 };
161 
162 //------------------------------------------------------------------------------
163 // CADHandle
164 //------------------------------------------------------------------------------
165 
CADHandle(unsigned char codeIn)166 CADHandle::CADHandle( unsigned char codeIn ) : code( codeIn )
167 {
168 }
169 
CADHandle(const CADHandle & other)170 CADHandle::CADHandle( const CADHandle& other ) :
171     code( other.code ),
172     handleOrOffset( other.handleOrOffset )
173 {
174 }
175 
operator =(const CADHandle & other)176 CADHandle& CADHandle::operator=( const CADHandle& other )
177 {
178     if( this == & other )
179         return * this;
180     code           = other.code;
181     handleOrOffset = other.handleOrOffset;
182     return * this;
183 }
184 
addOffset(unsigned char val)185 void CADHandle::addOffset( unsigned char val )
186 {
187     handleOrOffset.push_back( val );
188 }
189 
getAsLong(const CADHandle & ref_handle) const190 long CADHandle::getAsLong( const CADHandle& ref_handle ) const
191 {
192     // FIXME: Remove GDAL specific code. The library cannot compile as separate project.
193     try
194     {
195         switch( code )
196         {
197             case 0x06:
198             {
199                 return static_cast<long>((CPLSM(static_cast<GInt64>(getAsLong(ref_handle.handleOrOffset))) +
200                         CPLSM(static_cast<GInt64>(1))).v());
201             }
202             case 0x08:
203             {
204                 return static_cast<long>((CPLSM(static_cast<GInt64>(getAsLong(ref_handle.handleOrOffset))) -
205                         CPLSM(static_cast<GInt64>(1))).v());
206             }
207             case 0x0A:
208             {
209                 return static_cast<long>((CPLSM(static_cast<GInt64>(getAsLong(ref_handle.handleOrOffset))) +
210                         CPLSM(static_cast<GInt64>(getAsLong(handleOrOffset)))).v());
211             }
212             case 0x0C:
213             {
214                 return static_cast<long>((CPLSM(static_cast<GInt64>(getAsLong(ref_handle.handleOrOffset))) -
215                         CPLSM(static_cast<GInt64>(getAsLong(handleOrOffset)))).v());
216             }
217         }
218     }
219     catch( const CPLSafeIntOverflow& )
220     {
221         // TODO: handle this differently ?
222         return 0;
223     }
224 
225     return getAsLong(handleOrOffset);
226 }
227 
getAsLong() const228 long CADHandle::getAsLong() const
229 {
230     return getAsLong(handleOrOffset);
231 }
232 
getAsLong(const std::vector<unsigned char> & handle)233 long CADHandle::getAsLong(const std::vector<unsigned char>& handle)
234 {
235     unsigned long result = 0;
236     if( handle.empty() )
237         return result;
238     size_t copySize = handle.size();
239     if( copySize > sizeof(long) )
240         copySize = sizeof(long);
241     for( size_t i = 0; i < copySize; ++i )
242         result = result * 256U + handle[i];
243     return static_cast<long>(result);
244 }
245 
isNull() const246 bool CADHandle::isNull() const
247 {
248     return handleOrOffset.empty() ? true : false;
249 }
250 
251 //------------------------------------------------------------------------------
252 // CADVariant
253 //------------------------------------------------------------------------------
254 
CADVariant()255 CADVariant::CADVariant() :
256     type        ( DataType::INVALID ),
257     decimalVal  ( 0 ),
258     xVal        ( 0 ),
259     yVal        ( 0 ),
260     zVal        ( 0 ),
261     dateTimeVal ( 0 )
262 {
263 }
264 
CADVariant(const char * val)265 CADVariant::CADVariant( const char * val ) :
266     type        ( DataType::STRING ),
267     decimalVal  ( 0 ),
268     xVal        ( 0 ),
269     yVal        ( 0 ),
270     zVal        ( 0 ),
271     stringVal   ( string( val ) ),
272     dateTimeVal ( 0 )
273 {
274 }
275 
CADVariant(int val)276 CADVariant::CADVariant( int val ) :
277     type        ( DataType::DECIMAL ),
278     decimalVal  ( val ),
279     xVal        ( 0 ),
280     yVal        ( 0 ),
281     zVal        ( 0 ),
282     stringVal   ( to_string( val ) ),
283     dateTimeVal ( 0 )
284 {
285 }
286 
CADVariant(short val)287 CADVariant::CADVariant( short val ) :
288     type        ( DataType::DECIMAL ),
289     decimalVal  ( val ),
290     xVal        ( 0 ),
291     yVal        ( 0 ),
292     zVal        ( 0 ),
293     stringVal   ( to_string( val ) ),
294     dateTimeVal ( 0 )
295 {
296 }
297 
CADVariant(double val)298 CADVariant::CADVariant( double val ) :
299     type        ( DataType::REAL ),
300     decimalVal  ( 0 ),
301     xVal        ( val ),
302     yVal        ( 0 ),
303     zVal        ( 0 ),
304     stringVal   ( to_string( val ) ),
305     dateTimeVal ( 0 )
306 {
307 }
308 
CADVariant(double x,double y,double z)309 CADVariant::CADVariant( double x, double y, double z ) :
310     type        ( DataType::COORDINATES ),
311     decimalVal  ( 0 ),
312     xVal        ( x ),
313     yVal        ( y ),
314     zVal        ( z ),
315     dateTimeVal ( 0 )
316 {
317     char str_buff[256];
318     snprintf( str_buff, sizeof(str_buff), "[%.15g,%.15g,%.15g]", x, y, z );
319     str_buff[sizeof(str_buff)-1] = '\0';
320     stringVal = str_buff;
321 }
322 
CADVariant(const string & val)323 CADVariant::CADVariant( const string& val ) :
324     type        ( DataType::STRING ),
325     decimalVal  ( 0 ),
326     xVal        ( 0 ),
327     yVal        ( 0 ),
328     zVal        ( 0 ),
329     stringVal   ( val ),
330     dateTimeVal ( 0 )
331 {
332 }
333 
CADVariant(long julianday,long milliseconds)334 CADVariant::CADVariant( long julianday, long milliseconds ) :
335     type        ( DataType::DATETIME ),
336     decimalVal  ( 0 ),
337     xVal        ( 0 ),
338     yVal        ( 0 ),
339     zVal        ( 0 )
340 {
341     double dfSeconds = double( milliseconds ) / 1000;
342     double dfUnix = 0;
343     if(julianday != 0)
344         dfUnix = ( double( julianday ) - 2440587.5 ) * 86400.0;
345     dateTimeVal = static_cast<time_t>( dfUnix + dfSeconds );
346 
347     char str_buff[256] = "Invalid date";
348     struct tm *poLocaltime = localtime(&dateTimeVal);
349     if(poLocaltime)
350         strftime(str_buff, 255, "%Y-%m-%d %H:%M:%S", poLocaltime);
351     stringVal = str_buff;
352 }
353 
CADVariant(const CADHandle & val)354 CADVariant::CADVariant( const CADHandle& val ) :
355     type        ( DataType::HANDLE ),
356     decimalVal  ( 0 ),
357     xVal        ( 0 ),
358     yVal        ( 0 ),
359     zVal        ( 0 ),
360     stringVal   ( to_string( val.getAsLong() ) ),
361     handleVal   ( val ),
362     dateTimeVal ( 0 )
363 {
364 }
365 
getDecimal() const366 long CADVariant::getDecimal() const
367 {
368     return decimalVal;
369 }
370 
getReal() const371 double CADVariant::getReal() const
372 {
373     return xVal;
374 }
375 
getString() const376 const string& CADVariant::getString() const
377 {
378     return stringVal;
379 }
380 
getType() const381 CADVariant::DataType CADVariant::getType() const
382 {
383     return type;
384 }
385 
getX() const386 double CADVariant::getX() const
387 {
388     return xVal;
389 }
390 
getY() const391 double CADVariant::getY() const
392 {
393     return yVal;
394 }
395 
getZ() const396 double CADVariant::getZ() const
397 {
398     return zVal;
399 }
400 
getHandle() const401 const CADHandle& CADVariant::getHandle() const
402 {
403     return handleVal;
404 }
405 
406 //------------------------------------------------------------------------------
407 // CADHeader
408 //------------------------------------------------------------------------------
409 
CADHeader()410 CADHeader::CADHeader()
411 {
412 }
413 
addValue(short code,const CADVariant & val)414 int CADHeader::addValue( short code, const CADVariant& val )
415 {
416     if( valuesMap.find( code ) != valuesMap.end() )
417         return CADErrorCodes::VALUE_EXISTS;
418 
419     valuesMap[code] = val;
420     return CADErrorCodes::SUCCESS;
421 }
422 
addValue(short code,const char * val)423 int CADHeader::addValue( short code, const char * val )
424 {
425     return addValue( code, CADVariant( val ) );
426 }
427 /*
428 int CADHeader::addValue( short code, long val )
429 {
430     return addValue( code, CADVariant( val ) );
431 }
432 */
addValue(short code,int val)433 int CADHeader::addValue( short code, int val )
434 {
435     return addValue( code, CADVariant( val ) );
436 }
437 
addValue(short code,short val)438 int CADHeader::addValue( short code, short val )
439 {
440     return addValue( code, CADVariant( val ) );
441 }
442 
addValue(short code,double val)443 int CADHeader::addValue( short code, double val )
444 {
445     return addValue( code, CADVariant( val ) );
446 }
447 
addValue(short code,const string & val)448 int CADHeader::addValue( short code, const string& val )
449 {
450     return addValue( code, CADVariant( val ) );
451 }
452 
addValue(short code,bool val)453 int CADHeader::addValue( short code, bool val )
454 {
455     return addValue( code, CADVariant( val ? 1 : 0 ) );
456 }
457 
addValue(short code,double x,double y,double z)458 int CADHeader::addValue( short code, double x, double y, double z )
459 {
460     return addValue( code, CADVariant( x, y, z ) );
461 }
462 
addValue(short code,long julianday,long milliseconds)463 int CADHeader::addValue( short code, long julianday, long milliseconds )
464 {
465     // unix -> julian        return ( unixSecs / 86400.0 ) + 2440587.5;
466     // julian -> unix        return (julian - 2440587.5) * 86400.0
467 
468     return addValue( code, CADVariant( julianday, milliseconds ) );
469 }
470 
getGroupCode(short code)471 int CADHeader::getGroupCode( short code )
472 {
473     for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
474     {
475         if( detail.nConstant == code )
476             return detail.nGroupCode;
477     }
478 
479     return -1;
480 }
481 
getValue(short code,const CADVariant & val) const482 const CADVariant CADHeader::getValue( short code, const CADVariant& val ) const
483 {
484     auto it = valuesMap.find( code );
485     if( it != valuesMap.end() )
486         return it->second;
487     else
488         return val;
489 }
490 
getValueName(short code)491 const char * CADHeader::getValueName( short code )
492 {
493     for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
494     {
495         if( detail.nConstant == code )
496             return detail.pszValueName;
497     }
498     return "Undefined";
499 }
500 
print() const501 void CADHeader::print() const
502 {
503     cout << "============ HEADER Section ============\n";
504     for( auto it : valuesMap )
505     {
506         cout << getValueName( it.first ) << ": " << it.second.getString() << "\n";
507     }
508     cout << "\n";
509 }
510 
getSize() const511 size_t CADHeader::getSize() const
512 {
513     return valuesMap.size();
514 }
515 
getCode(int index) const516 short CADHeader::getCode( int index ) const
517 {
518     auto it = valuesMap.begin();
519     advance( it, index );
520     return it->first;
521 }
522