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 #include <dwg/io.h>
32 #include "cadheader.h"
33 #include "opencad_api.h"
34 
35 #include <cstring>
36 #include <iostream>
37 
38 using namespace std;
39 
40 typedef struct
41 {
42     short      nConstant;
43     short      nGroupCode;
44     const char * pszValueName;
45 } CADHeaderConstantDetail;
46 
47 #define FillCADConstantDetail( x, y ) {CADHeader::x, y, "$"#x}
48 
49 static const CADHeaderConstantDetail CADHeaderConstantDetails[]{
50         FillCADConstantDetail( ACADMAINTVER, 70 ), FillCADConstantDetail( ACADVER, 1 ),
51         FillCADConstantDetail( ANGBASE, 50 ), FillCADConstantDetail( ANGDIR, 70 ), FillCADConstantDetail( ATTMODE, 70 ),
52         FillCADConstantDetail( AUNITS, 70 ), FillCADConstantDetail( AUPREC, 70 ), FillCADConstantDetail( CECOLOR, 62 ),
53         FillCADConstantDetail( CELTSCALE, 40 ), FillCADConstantDetail( CELTYPE, 6 ),
54         FillCADConstantDetail( CELWEIGHT, 370 ), FillCADConstantDetail( CEPSNID, 390 ),
55         FillCADConstantDetail( CEPSNTYPE, 380 ), FillCADConstantDetail( CHAMFERA, 40 ),
56         FillCADConstantDetail( CHAMFERB, 40 ), FillCADConstantDetail( CHAMFERC, 40 ),
57         FillCADConstantDetail( CHAMFERD, 40 ), FillCADConstantDetail( CLAYER, 8 ), FillCADConstantDetail( CMLJUST, 70 ),
58         FillCADConstantDetail( CMLSCALE, 40 ), FillCADConstantDetail( CMLSTYLE, 2 ),
59         FillCADConstantDetail( CSHADOW, 280 ), FillCADConstantDetail( DIMADEC, 70 ),
60         FillCADConstantDetail( DIMALT, 70 ), FillCADConstantDetail( DIMALTD, 70 ), FillCADConstantDetail( DIMALTF, 40 ),
61         FillCADConstantDetail( DIMALTRND, 40 ), FillCADConstantDetail( DIMALTTD, 70 ),
62         FillCADConstantDetail( DIMALTTZ, 70 ), FillCADConstantDetail( DIMALTU, 70 ),
63         FillCADConstantDetail( DIMALTZ, 70 ), FillCADConstantDetail( DIMAPOST, 1 ), FillCADConstantDetail( DIMASO, 70 ),
64         FillCADConstantDetail( DIMASSOC, 280 ), FillCADConstantDetail( DIMASZ, 40 ),
65         FillCADConstantDetail( DIMATFIT, 70 ), FillCADConstantDetail( DIMAUNIT, 70 ),
66         FillCADConstantDetail( DIMAZIN, 70 ), FillCADConstantDetail( DIMBLK, 1 ), FillCADConstantDetail( DIMBLK1, 1 ),
67         FillCADConstantDetail( DIMBLK2, 1 ), FillCADConstantDetail( DIMCEN, 40 ), FillCADConstantDetail( DIMCLRD, 70 ),
68         FillCADConstantDetail( DIMCLRE, 70 ), FillCADConstantDetail( DIMCLRT, 70 ), FillCADConstantDetail( DIMDEC, 70 ),
69         FillCADConstantDetail( DIMDLE, 40 ), FillCADConstantDetail( DIMDLI, 40 ), FillCADConstantDetail( DIMDSEP, 70 ),
70         FillCADConstantDetail( DIMEXE, 40 ), FillCADConstantDetail( DIMEXO, 40 ), FillCADConstantDetail( DIMFAC, 40 ),
71         FillCADConstantDetail( DIMGAP, 40 ), FillCADConstantDetail( DIMJUST, 70 ),
72         FillCADConstantDetail( DIMLDRBLK, 1 ), FillCADConstantDetail( DIMLFAC, 40 ),
73         FillCADConstantDetail( DIMLIM, 70 ), FillCADConstantDetail( DIMLUNIT, 70 ), FillCADConstantDetail( DIMLWD, 70 ),
74         FillCADConstantDetail( DIMLWE, 70 ), FillCADConstantDetail( DIMPOST, 1 ), FillCADConstantDetail( DIMRND, 40 ),
75         FillCADConstantDetail( DIMSAH, 70 ), FillCADConstantDetail( DIMSCALE, 40 ), FillCADConstantDetail( DIMSD1, 70 ),
76         FillCADConstantDetail( DIMSD2, 70 ), FillCADConstantDetail( DIMSE1, 70 ), FillCADConstantDetail( DIMSE2, 70 ),
77         FillCADConstantDetail( DIMSHO, 70 ), FillCADConstantDetail( DIMSOXD, 70 ), FillCADConstantDetail( DIMSTYLE, 2 ),
78         FillCADConstantDetail( DIMTAD, 70 ), FillCADConstantDetail( DIMTDEC, 70 ), FillCADConstantDetail( DIMTFAC, 40 ),
79         FillCADConstantDetail( DIMTIH, 70 ), FillCADConstantDetail( DIMTIX, 70 ), FillCADConstantDetail( DIMTM, 40 ),
80         FillCADConstantDetail( DIMTMOVE, 70 ), FillCADConstantDetail( DIMTOFL, 70 ),
81         FillCADConstantDetail( DIMTOH, 70 ), FillCADConstantDetail( DIMTOL, 70 ), FillCADConstantDetail( DIMTOLJ, 70 ),
82         FillCADConstantDetail( DIMTP, 40 ), FillCADConstantDetail( DIMTSZ, 40 ), FillCADConstantDetail( DIMTVP, 40 ),
83         FillCADConstantDetail( DIMTXSTY, 7 ), FillCADConstantDetail( DIMTXT, 40 ), FillCADConstantDetail( DIMTZIN, 70 ),
84         FillCADConstantDetail( DIMUPT, 70 ), FillCADConstantDetail( DIMZIN, 70 ), FillCADConstantDetail( DISPSILH, 70 ),
85         FillCADConstantDetail( DRAGVS, 349 ), FillCADConstantDetail( DWGCODEPAGE, 3 ),
86         FillCADConstantDetail( ELEVATION, 40 ), FillCADConstantDetail( ENDCAPS, 280 ),
87         FillCADConstantDetail( EXTMAX, 123 ), FillCADConstantDetail( EXTMIN, 123 ),
88         FillCADConstantDetail( EXTNAMES, 290 ), FillCADConstantDetail( FILLETRAD, 40 ),
89         FillCADConstantDetail( FILLMODE, 70 ), FillCADConstantDetail( FINGERPRINTGUID, 2 ),
90         FillCADConstantDetail( HALOGAP, 280 ), FillCADConstantDetail( HANDSEED, 5 ),
91         FillCADConstantDetail( HIDETEXT, 290 ), FillCADConstantDetail( HYPERLINKBASE, 1 ),
92         FillCADConstantDetail( INDEXCTL, 280 ), FillCADConstantDetail( INSBASE, 123 ),
93         FillCADConstantDetail( INSUNITS, 70 ), FillCADConstantDetail( INTERFERECOLOR, 62 ),
94         FillCADConstantDetail( INTERFEREOBJVS, 345 ), FillCADConstantDetail( INTERFEREVPVS, 346 ),
95         FillCADConstantDetail( INTERSECTIONCOLOR, 70 ), FillCADConstantDetail( INTERSECTIONDISPLAY, 290 ),
96         FillCADConstantDetail( JOINSTYLE, 280 ), FillCADConstantDetail( LIMCHECK, 70 ),
97         FillCADConstantDetail( LIMMAX, 1020 ), FillCADConstantDetail( LIMMIN, 1020 ),
98         FillCADConstantDetail( LTSCALE, 40 ), FillCADConstantDetail( LUNITS, 70 ), FillCADConstantDetail( LUPREC, 70 ),
99         FillCADConstantDetail( LWDISPLAY, 290 ), FillCADConstantDetail( MAXACTVP, 70 ),
100         FillCADConstantDetail( MEASUREMENT, 70 ), FillCADConstantDetail( MENU, 1 ),
101         FillCADConstantDetail( MIRRTEXT, 70 ), FillCADConstantDetail( OBSCOLOR, 70 ),
102         FillCADConstantDetail( OBSLTYPE, 280 ), FillCADConstantDetail( ORTHOMODE, 70 ),
103         FillCADConstantDetail( PDMODE, 70 ), FillCADConstantDetail( PDSIZE, 40 ),
104         FillCADConstantDetail( PELEVATION, 40 ), FillCADConstantDetail( PEXTMAX, 123 ),
105         FillCADConstantDetail( PEXTMIN, 123 ), FillCADConstantDetail( PINSBASE, 123 ),
106         FillCADConstantDetail( PLIMCHECK, 70 ), FillCADConstantDetail( PLIMMAX, 1020 ),
107         FillCADConstantDetail( PLIMMIN, 1020 ), FillCADConstantDetail( PLINEGEN, 70 ),
108         FillCADConstantDetail( PLINEWID, 40 ), FillCADConstantDetail( PROJECTNAME, 1 ),
109         FillCADConstantDetail( PROXYGRAPHICS, 70 ), FillCADConstantDetail( PSLTSCALE, 70 ),
110         FillCADConstantDetail( PSTYLEMODE, 290 ), FillCADConstantDetail( PSVPSCALE, 40 ),
111         FillCADConstantDetail( PUCSBASE, 2 ), FillCADConstantDetail( PUCSNAME, 2 ),
112         FillCADConstantDetail( PUCSORG, 123 ), FillCADConstantDetail( PUCSORGBACK, 123 ),
113         FillCADConstantDetail( PUCSORGBOTTOM, 123 ), FillCADConstantDetail( PUCSORGFRONT, 123 ),
114         FillCADConstantDetail( PUCSORGLEFT, 123 ), FillCADConstantDetail( PUCSORGRIGHT, 123 ),
115         FillCADConstantDetail( PUCSORGTOP, 123 ), FillCADConstantDetail( PUCSORTHOREF, 2 ),
116         FillCADConstantDetail( PUCSORTHOVIEW, 70 ), FillCADConstantDetail( PUCSXDIR, 123 ),
117         FillCADConstantDetail( PUCSYDIR, 123 ), FillCADConstantDetail( QTEXTMODE, 70 ),
118         FillCADConstantDetail( REGENMODE, 70 ), FillCADConstantDetail( SHADEDGE, 70 ),
119         FillCADConstantDetail( SHADEDIF, 70 ), FillCADConstantDetail( SHADOWPLANELOCATION, 40 ),
120         FillCADConstantDetail( SKETCHINC, 40 ), FillCADConstantDetail( SKPOLY, 70 ),
121         FillCADConstantDetail( SORTENTS, 280 ), FillCADConstantDetail( SPLINESEGS, 70 ),
122         FillCADConstantDetail( SPLINETYPE, 70 ), FillCADConstantDetail( SURFTAB1, 70 ),
123         FillCADConstantDetail( SURFTAB2, 70 ), FillCADConstantDetail( SURFTYPE, 70 ),
124         FillCADConstantDetail( SURFU, 70 ), FillCADConstantDetail( SURFV, 70 ), FillCADConstantDetail( TDCREATE, 40 ),
125         FillCADConstantDetail( TDINDWG, 40 ), FillCADConstantDetail( TDUCREATE, 40 ),
126         FillCADConstantDetail( TDUPDATE, 40 ), FillCADConstantDetail( TDUSRTIMER, 40 ),
127         FillCADConstantDetail( TDUUPDATE, 40 ), FillCADConstantDetail( TEXTSIZE, 40 ),
128         FillCADConstantDetail( TEXTSTYLE, 7 ), FillCADConstantDetail( THICKNESS, 40 ),
129         FillCADConstantDetail( TILEMODE, 70 ), FillCADConstantDetail( TRACEWID, 40 ),
130         FillCADConstantDetail( TREEDEPTH, 70 ), FillCADConstantDetail( UCSBASE, 2 ),
131         FillCADConstantDetail( UCSNAME, 2 ), FillCADConstantDetail( UCSORG, 123 ),
132         FillCADConstantDetail( UCSORGBACK, 123 ), FillCADConstantDetail( UCSORGBOTTOM, 123 ),
133         FillCADConstantDetail( UCSORGFRONT, 123 ), FillCADConstantDetail( UCSORGLEFT, 123 ),
134         FillCADConstantDetail( UCSORGRIGHT, 123 ), FillCADConstantDetail( UCSORGTOP, 123 ),
135         FillCADConstantDetail( UCSORTHOREF, 2 ), FillCADConstantDetail( UCSORTHOVIEW, 70 ),
136         FillCADConstantDetail( UCSXDIR, 123 ), FillCADConstantDetail( UCSYDIR, 123 ),
137         FillCADConstantDetail( UNITMODE, 70 ), FillCADConstantDetail( USERI1, 70 ), FillCADConstantDetail( USERI2, 70 ),
138         FillCADConstantDetail( USERI3, 70 ), FillCADConstantDetail( USERI4, 70 ), FillCADConstantDetail( USERI5, 70 ),
139         FillCADConstantDetail( USERR1, 40 ), FillCADConstantDetail( USERR2, 40 ), FillCADConstantDetail( USERR3, 40 ),
140         FillCADConstantDetail( USERR4, 40 ), FillCADConstantDetail( USERR5, 40 ), FillCADConstantDetail( USRTIMER, 70 ),
141         FillCADConstantDetail( VERSIONGUID, 2 ), FillCADConstantDetail( VISRETAIN, 70 ),
142         FillCADConstantDetail( WORLDVIEW, 70 ), FillCADConstantDetail( XCLIPFRAME, 290 ),
143         FillCADConstantDetail( XEDIT, 290 ), { -1, -1, NULL }
144 };
145 
146 //------------------------------------------------------------------------------
147 // CADHandle
148 //------------------------------------------------------------------------------
149 
CADHandle(unsigned char codeIn)150 CADHandle::CADHandle( unsigned char codeIn ) : code( codeIn )
151 {
152 }
153 
CADHandle(const CADHandle & other)154 CADHandle::CADHandle( const CADHandle& other )
155 {
156     code           = other.code;
157     handleOrOffset = other.handleOrOffset;
158 }
159 
operator =(const CADHandle & other)160 CADHandle& CADHandle::operator=( const CADHandle& other )
161 {
162     if( this == & other )
163         return * this;
164     code           = other.code;
165     handleOrOffset = other.handleOrOffset;
166     return * this;
167 }
168 
addOffset(unsigned char val)169 void CADHandle::addOffset( unsigned char val )
170 {
171     handleOrOffset.push_back( val );
172 }
173 
getAsLong(const CADHandle & ref_handle) const174 long CADHandle::getAsLong( const CADHandle& ref_handle ) const
175 {
176     long result = 0;
177     switch( code )
178     {
179         case 0x06:
180         {
181             memcpy( & result, ref_handle.handleOrOffset.data(), ref_handle.handleOrOffset.size() );
182             SwapEndianness( result, ref_handle.handleOrOffset.size() );
183             return result + 1;
184         }
185         case 0x08:
186         {
187             memcpy( & result, ref_handle.handleOrOffset.data(), ref_handle.handleOrOffset.size() );
188             SwapEndianness( result, ref_handle.handleOrOffset.size() );
189             return result - 1;
190         }
191         case 0x0A:
192         {
193             memcpy( & result, ref_handle.handleOrOffset.data(), ref_handle.handleOrOffset.size() );
194             SwapEndianness( result, ref_handle.handleOrOffset.size() );
195             return result + this->getAsLong();
196         }
197         case 0x0C:
198         {
199             memcpy( & result, ref_handle.handleOrOffset.data(), ref_handle.handleOrOffset.size() );
200             SwapEndianness( result, ref_handle.handleOrOffset.size() );
201             return result - this->getAsLong();
202         }
203     }
204 
205     return this->getAsLong();
206 }
207 
getAsLong() const208 long CADHandle::getAsLong() const
209 {
210     long result = 0;
211     memcpy( & result, handleOrOffset.data(), handleOrOffset.size() );
212     SwapEndianness( result, handleOrOffset.size() );
213     return result;
214 }
215 
isNull() const216 bool CADHandle::isNull() const
217 {
218     return handleOrOffset.size() == 0 ? true : false;
219 }
220 
221 //------------------------------------------------------------------------------
222 // CADVariant
223 //------------------------------------------------------------------------------
224 
CADVariant()225 CADVariant::CADVariant()
226 {
227     type        = DataType::INVALID;
228     decimalVal  = 0;
229     xVal        = 0;
230     yVal        = 0;
231     zVal        = 0;
232     dateTimeVal = 0;
233 }
234 
CADVariant(const char * val)235 CADVariant::CADVariant( const char * val )
236 {
237     type        = DataType::STRING;
238     stringVal   = string( val );
239     decimalVal  = 0;
240     xVal        = 0;
241     yVal        = 0;
242     zVal        = 0;
243     dateTimeVal = 0;
244 }
245 
CADVariant(long val)246 CADVariant::CADVariant( long val )
247 {
248     type        = DataType ::DECIMAL;
249     decimalVal  = val;
250     stringVal   = to_string( decimalVal );
251     xVal        = 0;
252     yVal        = 0;
253     zVal        = 0;
254     dateTimeVal = 0;
255 }
256 
CADVariant(int val)257 CADVariant::CADVariant( int val )
258 {
259     type        = DataType::DECIMAL;
260     decimalVal  = val;
261     stringVal   = to_string( decimalVal );
262     xVal        = 0;
263     yVal        = 0;
264     zVal        = 0;
265     dateTimeVal = 0;
266 }
267 
CADVariant(short val)268 CADVariant::CADVariant( short val )
269 {
270     type        = DataType::DECIMAL;
271     decimalVal  = val;
272     stringVal   = to_string( decimalVal );
273     xVal        = 0;
274     yVal        = 0;
275     zVal        = 0;
276     dateTimeVal = 0;
277 }
278 
CADVariant(double val)279 CADVariant::CADVariant( double val )
280 {
281     type        = DataType::REAL;
282     xVal        = val;
283     stringVal   = to_string( xVal );
284     decimalVal  = 0;
285     yVal        = 0;
286     zVal        = 0;
287     dateTimeVal = 0;
288 }
289 
CADVariant(double x,double y,double z)290 CADVariant::CADVariant( double x, double y, double z )
291 {
292     type = DataType::COORDINATES;
293     xVal = x;
294     yVal = y;
295     zVal = z;
296 
297     char str_buff[256];
298     snprintf( str_buff, 255, "[%f,%f,%f]", x, y, z );
299     stringVal = str_buff;
300 
301     decimalVal  = 0;
302     dateTimeVal = 0;
303 }
304 
CADVariant(const string & val)305 CADVariant::CADVariant( const string& val )
306 {
307     type      = DataType::STRING;
308     stringVal = val;
309 
310     decimalVal  = 0;
311     xVal        = 0;
312     yVal        = 0;
313     zVal        = 0;
314     dateTimeVal = 0;
315 }
316 
CADVariant(time_t val,bool bIsTime)317 CADVariant::CADVariant( time_t val, bool bIsTime )
318 {
319     type        = DataType::DATETIME;
320     dateTimeVal = val;
321 
322     //TODO: data/time format
323     char str_buff[256];
324     snprintf( str_buff, 255, "%ld", dateTimeVal );
325     stringVal = str_buff;
326 
327     decimalVal = 0;
328     xVal       = 0;
329     yVal       = 0;
330     zVal       = 0;
331 }
332 
CADVariant(const CADHandle & val)333 CADVariant::CADVariant( const CADHandle& val )
334 {
335     type      = DataType::HANDLE;
336     handleVal = val;
337     stringVal = to_string( val.getAsLong() );
338 
339     decimalVal  = 0;
340     xVal        = 0;
341     yVal        = 0;
342     zVal        = 0;
343     dateTimeVal = 0;
344 }
345 
CADVariant(const CADVariant & orig)346 CADVariant::CADVariant( const CADVariant& orig )
347 {
348     type        = orig.type;
349     stringVal   = orig.stringVal;
350     decimalVal  = orig.decimalVal;
351     xVal        = orig.xVal;
352     yVal        = orig.yVal;
353     zVal        = orig.zVal;
354     handleVal   = orig.handleVal;
355     dateTimeVal = orig.dateTimeVal;
356 }
357 
operator =(const CADVariant & orig)358 CADVariant& CADVariant::operator=( const CADVariant& orig )
359 {
360     if( this == & orig )
361         return * this;
362     type        = orig.type;
363     stringVal   = orig.stringVal;
364     decimalVal  = orig.decimalVal;
365     xVal        = orig.xVal;
366     yVal        = orig.yVal;
367     zVal        = orig.zVal;
368     handleVal   = orig.handleVal;
369     dateTimeVal = orig.dateTimeVal;
370     return * this;
371 }
372 
getDecimal() const373 long CADVariant::getDecimal() const
374 {
375     return decimalVal;
376 }
377 
getReal() const378 double CADVariant::getReal() const
379 {
380     return xVal;
381 }
382 
getString() const383 const string& CADVariant::getString() const
384 {
385     return stringVal;
386 }
387 
getType() const388 CADVariant::DataType CADVariant::getType() const
389 {
390     return type;
391 }
392 
getX() const393 double CADVariant::getX() const
394 {
395     return xVal;
396 }
397 
getY() const398 double CADVariant::getY() const
399 {
400     return yVal;
401 }
402 
getZ() const403 double CADVariant::getZ() const
404 {
405     return zVal;
406 }
407 
getHandle() const408 const CADHandle& CADVariant::getHandle() const
409 {
410     return handleVal;
411 }
412 
413 //------------------------------------------------------------------------------
414 // CADHeader
415 //------------------------------------------------------------------------------
416 
CADHeader()417 CADHeader::CADHeader()
418 {
419 }
420 
addValue(short code,const CADVariant & val)421 int CADHeader::addValue( short code, const CADVariant& val )
422 {
423     if( valuesMap.find( code ) != valuesMap.end() )
424         return CADErrorCodes::VALUE_EXISTS;
425 
426     valuesMap[code] = val;
427     return CADErrorCodes::SUCCESS;
428 }
429 
addValue(short code,const char * val)430 int CADHeader::addValue( short code, const char * val )
431 {
432     return addValue( code, CADVariant( val ) );
433 }
434 
addValue(short code,long val)435 int CADHeader::addValue( short code, long val )
436 {
437     return addValue( code, CADVariant( val ) );
438 }
439 
addValue(short code,int val)440 int CADHeader::addValue( short code, int val )
441 {
442     return addValue( code, CADVariant( val ) );
443 }
444 
addValue(short code,short val)445 int CADHeader::addValue( short code, short val )
446 {
447     return addValue( code, CADVariant( val ) );
448 }
449 
addValue(short code,double val)450 int CADHeader::addValue( short code, double val )
451 {
452     return addValue( code, CADVariant( val ) );
453 }
454 
addValue(short code,const string & val)455 int CADHeader::addValue( short code, const string& val )
456 {
457     return addValue( code, CADVariant( val ) );
458 }
459 
addValue(short code,bool val)460 int CADHeader::addValue( short code, bool val )
461 {
462     return addValue( code, CADVariant( val ? 1 : 0 ) );
463 }
464 
addValue(short code,double x,double y,double z)465 int CADHeader::addValue( short code, double x, double y, double z )
466 {
467     return addValue( code, CADVariant( x, y, z ) );
468 }
469 
addValue(short code,long julianday,long milliseconds)470 int CADHeader::addValue( short code, long julianday, long milliseconds )
471 {
472     // unix -> julian        return ( unixSecs / 86400.0 ) + 2440587.5;
473     // julian -> unix        return (julian - 2440587.5) * 86400.0
474 
475     double seconds     = double( milliseconds ) / 1000;
476     double unix        = ( double( julianday ) - 2440587.5 ) * 86400.0;
477     time_t fullSeconds = static_cast<time_t>(unix + seconds);
478     return addValue( code, CADVariant( fullSeconds ) );
479 }
480 
getGroupCode(short code) const481 int CADHeader::getGroupCode( short code ) const
482 {
483     for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
484     {
485         if( detail.nConstant == code )
486             return detail.nGroupCode;
487     }
488 
489     return -1;
490 }
491 
getValue(short code,const CADVariant & val) const492 const CADVariant CADHeader::getValue( short code, const CADVariant& val ) const
493 {
494     auto it = valuesMap.find( code );
495     if( it != valuesMap.end() )
496         return it->second;
497     else
498         return val;
499 }
500 
getValueName(short code) const501 const char * CADHeader::getValueName( short code ) const
502 {
503     for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
504     {
505         if( detail.nConstant == code )
506             return detail.pszValueName;
507     }
508     return "Undefined";
509 }
510 
print() const511 void CADHeader::print() const
512 {
513     cout << "============ HEADER Section ============" << endl;
514     for( auto it : valuesMap )
515     {
516         cout << getValueName( it.first ) << ": " << it.second.getString() << endl;
517     }
518 }
519 
getSize() const520 size_t CADHeader::getSize() const
521 {
522     return valuesMap.size();
523 }
524 
getCode(int index) const525 short CADHeader::getCode( int index ) const
526 {
527     auto it = valuesMap.begin();
528     advance( it, index );
529     return it->first;
530 }
531