1 /**********************************************************
2  * Version $Id: dl_dxf.cpp 911 2011-02-14 16:38:15Z reklov_w $
3  *********************************************************/
4 /****************************************************************************
5 ** $Id: dl_dxf.cpp 911 2011-02-14 16:38:15Z reklov_w $
6 **
7 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
8 **
9 ** This file is part of the dxflib project.
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.GPL included in the
14 ** packaging of this file.
15 **
16 ** Licensees holding valid dxflib Professional Edition licenses may use
17 ** this file in accordance with the dxflib Commercial License
18 ** Agreement provided with the Software.
19 **
20 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
21 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 **
23 ** See http://www.ribbonsoft.com for further details.
24 **
25 ** Contact info@ribbonsoft.com if any conditions of this licensing are
26 ** not clear to you.
27 **
28 **********************************************************************/
29 
30 #include "dl_dxf.h"
31 
32 #include <algorithm>
33 #include <string>
34 #include <cstdio>
35 #include <cassert>
36 #include <cmath>
37 
38 #include "dl_attributes.h"
39 #include "dl_codes.h"
40 #include "dl_creationinterface.h"
41 #include "dl_writer_ascii.h"
42 
43 
44 /**
45  * Default constructor.
46  */
DL_Dxf()47 DL_Dxf::DL_Dxf() {
48     styleHandleStd = 0;
49     version = VER_2000;
50 
51     vertices = NULL;
52     maxVertices = 0;
53     vertexIndex = 0;
54 
55     knots = NULL;
56     maxKnots = 0;
57     knotIndex = 0;
58 
59     controlPoints = NULL;
60     maxControlPoints = 0;
61     controlPointIndex = 0;
62 
63     leaderVertices = NULL;
64     maxLeaderVertices = 0;
65     leaderVertexIndex = 0;
66 
67     hatchLoops = NULL;
68     maxHatchLoops = 0;
69     hatchLoopIndex = -1;
70     hatchEdges = NULL;
71     maxHatchEdges = NULL;
72     hatchEdgeIndex = NULL;
73     dropEdges = false;
74 }
75 
76 
77 
78 /**
79  * Destructor.
80  */
~DL_Dxf()81 DL_Dxf::~DL_Dxf() {
82     if (vertices!=NULL) {
83         delete[] vertices;
84     }
85     if (knots!=NULL) {
86         delete[] knots;
87     }
88     if (controlPoints!=NULL) {
89         delete[] controlPoints;
90     }
91     if (leaderVertices!=NULL) {
92         delete[] leaderVertices;
93     }
94     if (hatchLoops!=NULL) {
95         delete[] hatchLoops;
96     }
97     if (hatchEdges!=NULL) {
98         for (int i=0; i<maxHatchLoops; ++i) {
99             if (hatchEdges[i]!=NULL) {
100                 delete[] hatchEdges[i];
101             }
102         }
103         delete[] hatchEdges;
104     }
105     if (maxHatchEdges!=NULL) {
106         delete[] maxHatchEdges;
107     }
108     if (hatchEdgeIndex!=NULL) {
109         delete[] hatchEdgeIndex;
110     }
111 }
112 
113 
114 
115 /**
116  * @brief Reads the given file and calls the appropriate functions in
117  * the given creation interface for every entity found in the file.
118  *
119  * @param file Input
120  *		Path and name of file to read
121  * @param creationInterface
122  *		Pointer to the class which takes care of the entities in the file.
123  *
124  * @retval true If \p file could be opened.
125  * @retval false If \p file could not be opened.
126  */
in(const string & file,DL_CreationInterface * creationInterface)127 bool DL_Dxf::in(const string& file, DL_CreationInterface* creationInterface) {
128     FILE *fp;
129     firstCall = true;
130     currentEntity = DL_UNKNOWN;
131     int errorCounter = 0;
132 
133     fp = fopen(file.c_str(), "rt");
134     if (fp) {
135         while (readDxfGroups(fp, creationInterface, &errorCounter)) {}
136         fclose(fp);
137         if (errorCounter>0) {
138             std::cerr << "DXF Filter: There have been " << errorCounter <<
139             " errors. The drawing might be incomplete / incorrect.\n";
140         }
141         return true;
142     }
143 
144     return false;
145 }
146 
147 
148 
149 /**
150  * Reads a DXF file from an existing stream.
151  *
152  * @param stream The string stream.
153  * @param creationInterface
154  *		Pointer to the class which takes care of the entities in the file.
155  *
156  * @retval true If \p file could be opened.
157  * @retval false If \p file could not be opened.
158  */
159 #ifndef __GCC2x__
in(std::stringstream & stream,DL_CreationInterface * creationInterface)160 bool DL_Dxf::in(std::stringstream& stream,
161                 DL_CreationInterface* creationInterface) {
162 
163     int errorCounter = 0;
164 
165     if (stream.good()) {
166         firstCall=true;
167         currentEntity = DL_UNKNOWN;
168         while (readDxfGroups(stream, creationInterface, &errorCounter)) {}
169         if (errorCounter>0) {
170             std::cerr << "DXF Filter: There have been " << errorCounter <<
171             " errors. The drawing might be incomplete / incorrect.\n";
172         }
173         return true;
174     }
175     return false;
176 }
177 #endif
178 
179 
180 
181 /**
182  * @brief Reads a group couplet from a DXF file.  Calls another function
183  * to process it.
184  *
185  * A group couplet consists of two lines that represent a single
186  * piece of data.  An integer constant on the first line indicates
187  * the type of data.  The value is on the next line.\n
188  *
189  * This function reads a couplet, determines the type of data, and
190  * passes the value to the the appropriate handler function of
191  * \p creationInterface.\n
192  *
193  * \p fp is advanced so that the next call to \p readDXFGroups() reads
194  * the next couplet in the file.
195  *
196  * @param fp Handle of input file
197  * @param creationInterface Handle of class which processes entities
198  *		in the file
199  *
200  * @retval true If EOF not reached.
201  * @retval false If EOF reached.
202  */
readDxfGroups(FILE * fp,DL_CreationInterface * creationInterface,int * errorCounter)203 bool DL_Dxf::readDxfGroups(FILE *fp, DL_CreationInterface* creationInterface,
204                            int* errorCounter) {
205 
206     bool ok = true;
207     static int line = 1;
208 
209     // Read one group of the DXF file and chop the lines:
210     if (DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, fp) &&
211             DL_Dxf::getChoppedLine(groupValue, DL_DXF_MAXLINE, fp) ) {
212 
213         groupCode = (unsigned int)stringToInt(groupCodeTmp, &ok);
214 
215         if (ok) {
216             //std::cerr << groupCode << "\n";
217             //std::cerr << groupValue << "\n";
218             line+=2;
219             processDXFGroup(creationInterface, groupCode, groupValue);
220         } else {
221             std::cerr << "DXF read error: Line: " << line << "\n";
222             if (errorCounter!=NULL) {
223                 (*errorCounter)++;
224             }
225             // try to fix:
226             std::cerr << "DXF read error: trying to fix..\n";
227             // drop a line to sync:
228             DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, fp);
229         }
230     }
231 
232     return !feof(fp);
233 }
234 
235 
236 
237 /**
238  * Same as above but for stringstreams.
239  */
240 #ifndef __GCC2x__
readDxfGroups(std::stringstream & stream,DL_CreationInterface * creationInterface,int * errorCounter)241 bool DL_Dxf::readDxfGroups(std::stringstream& stream,
242                            DL_CreationInterface* creationInterface,
243                            int* errorCounter) {
244 
245     bool ok = true;
246     static int line = 1;
247 
248     // Read one group of the DXF file and chop the lines:
249     if (DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, stream) &&
250             DL_Dxf::getChoppedLine(groupValue, DL_DXF_MAXLINE, stream) ) {
251 
252         groupCode = (unsigned int)stringToInt(groupCodeTmp, &ok);
253 
254         if (ok) {
255             //std::cout << "group code: " << groupCode << "\n";
256             //std::cout << "group value: " << groupValue << "\n";
257             line+=2;
258             processDXFGroup(creationInterface, groupCode, groupValue);
259         } else {
260             std::cerr << "DXF read error: Line: " << line << "\n";
261             if (errorCounter!=NULL) {
262                 (*errorCounter)++;
263             }
264             // try to fix:
265             //std::cerr << "DXF read error: trying to fix..\n";
266             // drop a line to sync:
267             //DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, stream);
268         }
269     }
270     return !stream.eof();
271 }
272 #endif
273 
274 
275 
276 /**
277  * @brief Reads line from file & strips whitespace at start and newline
278  * at end.
279  *
280  * @param s Output\n
281  *		Pointer to character array that chopped line will be returned in.
282  * @param size Size of \p s.  (Including space for NULL.)
283  * @param fp Input\n
284  *		Handle of input file.
285  *
286  * @retval true if line could be read
287  * @retval false if \p fp is already at end of file
288  *
289  * @todo Change function to use safer FreeBSD strl* functions
290  * @todo Is it a problem if line is blank (i.e., newline only)?
291  *		Then, when function returns, (s==NULL).
292  */
getChoppedLine(char * s,unsigned int size,FILE * fp)293 bool DL_Dxf::getChoppedLine(char *s, unsigned int size, FILE *fp) {
294     if (!feof(fp)) {
295         // The whole line in the file.  Includes space for NULL.
296         char* wholeLine = new char[size];
297         // Only the useful part of the line
298         char* line;
299 
300         line = fgets(wholeLine, size, fp);
301 
302         if (line!=NULL && line[0] != '\0') { // Evaluates to fgets() retval
303             // line == wholeLine at this point.
304             // Both guaranteed to be NULL terminated.
305 
306             // Strip leading whitespace and trailing CR/LF.
307             stripWhiteSpace(&line);
308 
309             strncpy(s, line, size);
310             s[size] = '\0';
311             // s should always be NULL terminated, because:
312             assert(size > strlen(line));
313         }
314 
315         delete[] wholeLine; // Done with wholeLine
316 
317         return true;
318     } else {
319         s[0] = '\0';
320         return false;
321     }
322 }
323 
324 
325 
326 /**
327  * Same as above but for stringstreams.
328  */
329 #ifndef __GCC2x__
getChoppedLine(char * s,unsigned int size,std::stringstream & stream)330 bool DL_Dxf::getChoppedLine(char *s, unsigned int size,
331                             std::stringstream& stream) {
332 
333     if (!stream.eof()) {
334         // Only the useful part of the line
335         char* line = new char[size+1];
336         char* oriLine = line;
337         stream.getline(line, size);
338         stripWhiteSpace(&line);
339         strncpy(s, line, size);
340         s[size] = '\0';
341         assert(size > strlen(s));
342         delete[] oriLine;
343         return true;
344     } else {
345         s[0] = '\0';
346         return false;
347     }
348 }
349 #endif
350 
351 
352 
353 /**
354  * @brief Strips leading whitespace and trailing Carriage Return (CR)
355  * and Line Feed (LF) from NULL terminated string.
356  *
357  * @param s Input and output.
358  *		NULL terminates string.
359  *
360  * @retval true if \p s is non-NULL
361  * @retval false if \p s is NULL
362  */
stripWhiteSpace(char ** s)363 bool DL_Dxf::stripWhiteSpace(char** s) {
364     // last non-NULL char:
365     int lastChar = strlen(*s) - 1;
366 
367     // Is last character CR or LF?
368     while ( (lastChar >= 0) &&
369             (((*s)[lastChar] == 10) || ((*s)[lastChar] == 13) ||
370              ((*s)[lastChar] == ' ' || ((*s)[lastChar] == '\t'))) ) {
371         (*s)[lastChar] = '\0';
372         lastChar--;
373     }
374 
375     // Skip whitespace, excluding \n, at beginning of line
376     while ((*s)[0]==' ' || (*s)[0]=='\t') {
377         ++(*s);
378     }
379 
380     return ((*s) ? true : false);
381 }
382 
383 
384 
385 /**
386  * Processes a group (pair of group code and value).
387  *
388  * @param creationInterface Handle to class that creates entities and
389  * other CAD data from DXF group codes
390  *
391  * @param groupCode Constant indicating the data type of the group.
392  * @param groupValue The data value.
393  *
394  * @retval true if done processing current entity and new entity begun
395  * @retval false if not done processing current entity
396 */
processDXFGroup(DL_CreationInterface * creationInterface,int groupCode,const char * groupValue)397 bool DL_Dxf::processDXFGroup(DL_CreationInterface* creationInterface,
398                              int groupCode, const char *groupValue) {
399 
400     // Init on first call
401     if (firstCall) {
402         for (int i=0; i<DL_DXF_MAXGROUPCODE; ++i) {
403             values[i][0] = '\0';
404         }
405         settingValue[0] = '\0';
406         firstCall=false;
407     }
408 
409     // Indicates comment or dxflib version:
410     if (groupCode==999) {
411         if (groupValue!=NULL) {
412             if (!strncmp(groupValue, "dxflib", 6)) {
413                 libVersion = getLibVersion(&groupValue[7]);
414             }
415 
416             addComment(creationInterface, groupValue);
417         }
418     }
419 
420     // Indicates start of new entity or var
421     else if (groupCode==0 || groupCode==9) {
422 
423         // If new entity is encountered, the last one must be complete
424         // prepare attributes which can be used for most entities:
425         char name[DL_DXF_MAXLINE+1];
426         if ((values[8])[0]!='\0') {
427             strcpy(name, values[8]);
428         }
429         // defaults to layer '0':
430         else {
431             strcpy(name, "0");
432         }
433 
434         int width;
435         // Compatibillity with qcad1:
436         if ((values[39])[0]!='\0' &&
437                 (values[370])[0]=='\0') {
438             width = toInt(values[39], -1);
439         }
440         // since autocad 2002:
441         else if ((values[370])[0]!='\0') {
442             width = toInt(values[370], -1);
443         }
444         // default to BYLAYER:
445         else {
446             width = -1;
447         }
448 
449         int color;
450         color = toInt(values[62], 256);
451 
452         char linetype[DL_DXF_MAXLINE+1];
453         strcpy(linetype, toString(values[6], "BYLAYER"));
454 
455         attrib = DL_Attributes(values[8],          // layer
456                                color,              // color
457                                width,              // width
458                                linetype);          // linetype
459         creationInterface->setAttributes(attrib);
460 
461         creationInterface->setExtrusion(toReal(values[210], 0.0),
462                                         toReal(values[220], 0.0),
463                                         toReal(values[230], 1.0),
464                                         toReal(values[30], 0.0));
465 
466         // Add the last entity via creationInterface
467         switch (currentEntity) {
468         case DL_SETTING:
469             addSetting(creationInterface);
470             break;
471 
472         case DL_LAYER:
473             addLayer(creationInterface);
474             break;
475 
476         case DL_BLOCK:
477             addBlock(creationInterface);
478             break;
479 
480         case DL_ENDBLK:
481             endBlock(creationInterface);
482             break;
483 
484         case DL_ENTITY_POINT:
485             addPoint(creationInterface);
486             break;
487 
488         case DL_ENTITY_LINE:
489             addLine(creationInterface);
490             break;
491 
492         case DL_ENTITY_POLYLINE:
493             //bulge = toReal(values[42]);
494             // fall through
495         case DL_ENTITY_LWPOLYLINE:
496             addPolyline(creationInterface);
497             break;
498 
499         case DL_ENTITY_VERTEX:
500             addVertex(creationInterface);
501             break;
502 
503         case DL_ENTITY_SPLINE:
504             addSpline(creationInterface);
505             break;
506 
507         case DL_ENTITY_ARC:
508             addArc(creationInterface);
509             break;
510 
511         case DL_ENTITY_CIRCLE:
512             addCircle(creationInterface);
513             break;
514 
515         case DL_ENTITY_ELLIPSE:
516             addEllipse(creationInterface);
517             break;
518 
519         case DL_ENTITY_INSERT:
520             addInsert(creationInterface);
521             break;
522 
523         case DL_ENTITY_MTEXT:
524             addMText(creationInterface);
525             break;
526 
527         case DL_ENTITY_TEXT:
528             addText(creationInterface);
529             break;
530 
531         case DL_ENTITY_ATTRIB:
532             addAttrib(creationInterface);
533             break;
534 
535         case DL_ENTITY_DIMENSION: {
536                 int type = (toInt(values[70], 0)&0x07);
537 
538                 switch (type) {
539                 case 0:
540                     addDimLinear(creationInterface);
541                     break;
542 
543                 case 1:
544                     addDimAligned(creationInterface);
545                     break;
546 
547                 case 2:
548                     addDimAngular(creationInterface);
549                     break;
550 
551                 case 3:
552                     addDimDiametric(creationInterface);
553                     break;
554 
555                 case 4:
556                     addDimRadial(creationInterface);
557                     break;
558 
559                 case 5:
560                     addDimAngular3P(creationInterface);
561                     break;
562 
563                 case 6:
564                     addDimOrdinate(creationInterface);
565                     break;
566 
567                 default:
568                     break;
569                 }
570             }
571             break;
572 
573         case DL_ENTITY_LEADER:
574             addLeader(creationInterface);
575             break;
576 
577         case DL_ENTITY_HATCH:
578             addHatch(creationInterface);
579             break;
580 
581         case DL_ENTITY_IMAGE:
582             addImage(creationInterface);
583             break;
584 
585         case DL_ENTITY_IMAGEDEF:
586             addImageDef(creationInterface);
587             break;
588 
589         case DL_ENTITY_TRACE:
590             addTrace(creationInterface);
591             break;
592 
593         case DL_ENTITY_3DFACE:
594             add3dFace(creationInterface);
595             break;
596 
597         case DL_ENTITY_SOLID:
598             addSolid(creationInterface);
599             break;
600 
601         case DL_ENTITY_SEQEND:
602             endSequence(creationInterface);
603             break;
604 
605         default:
606             break;
607         }
608 
609 
610         // reset all values (they are not persistent and only this
611         //  way we can detect default values for unstored settings)
612         for (int i=0; i<DL_DXF_MAXGROUPCODE; ++i) {
613             values[i][0] = '\0';
614         }
615         settingValue[0] = '\0';
616         settingKey[0] = '\0';
617 
618 
619         // Last DXF entity or setting has been handled
620         // Now determine what the next entity or setting type is
621 
622 		int prevEntity = currentEntity;
623 
624         // Read DXF settings:
625         if (groupValue[0]=='$') {
626             currentEntity = DL_SETTING;
627             strncpy(settingKey, groupValue, DL_DXF_MAXLINE);
628             settingKey[DL_DXF_MAXLINE] = '\0';
629         }
630         // Read Layers:
631         else if (!strcmp(groupValue, "LAYER")) {
632             currentEntity = DL_LAYER;
633 
634         }
635         // Read Blocks:
636         else if (!strcmp(groupValue, "BLOCK")) {
637             currentEntity = DL_BLOCK;
638         } else if (!strcmp(groupValue, "ENDBLK")) {
639             currentEntity = DL_ENDBLK;
640 
641         }
642         // Read entities:
643         else if (!strcmp(groupValue, "POINT")) {
644             currentEntity = DL_ENTITY_POINT;
645         } else if (!strcmp(groupValue, "LINE")) {
646             currentEntity = DL_ENTITY_LINE;
647         } else if (!strcmp(groupValue, "POLYLINE")) {
648             currentEntity = DL_ENTITY_POLYLINE;
649         } else if (!strcmp(groupValue, "LWPOLYLINE")) {
650             currentEntity = DL_ENTITY_LWPOLYLINE;
651         } else if (!strcmp(groupValue, "VERTEX")) {
652             currentEntity = DL_ENTITY_VERTEX;
653         } else if (!strcmp(groupValue, "SPLINE")) {
654             currentEntity = DL_ENTITY_SPLINE;
655         } else if (!strcmp(groupValue, "ARC")) {
656             currentEntity = DL_ENTITY_ARC;
657         } else if (!strcmp(groupValue, "ELLIPSE")) {
658             currentEntity = DL_ENTITY_ELLIPSE;
659         } else if (!strcmp(groupValue, "CIRCLE")) {
660             currentEntity = DL_ENTITY_CIRCLE;
661         } else if (!strcmp(groupValue, "INSERT")) {
662             currentEntity = DL_ENTITY_INSERT;
663         } else if (!strcmp(groupValue, "TEXT")) {
664             currentEntity = DL_ENTITY_TEXT;
665         } else if (!strcmp(groupValue, "MTEXT")) {
666             currentEntity = DL_ENTITY_MTEXT;
667         } else if (!strcmp(groupValue, "ATTRIB")) {
668             currentEntity = DL_ENTITY_ATTRIB;
669         } else if (!strcmp(groupValue, "DIMENSION")) {
670             currentEntity = DL_ENTITY_DIMENSION;
671         } else if (!strcmp(groupValue, "LEADER")) {
672             currentEntity = DL_ENTITY_LEADER;
673         } else if (!strcmp(groupValue, "HATCH")) {
674             currentEntity = DL_ENTITY_HATCH;
675         } else if (!strcmp(groupValue, "IMAGE")) {
676             currentEntity = DL_ENTITY_IMAGE;
677         } else if (!strcmp(groupValue, "IMAGEDEF")) {
678             currentEntity = DL_ENTITY_IMAGEDEF;
679         } else if (!strcmp(groupValue, "TRACE")) {
680            currentEntity = DL_ENTITY_TRACE;
681         } else if (!strcmp(groupValue, "SOLID")) {
682            currentEntity = DL_ENTITY_SOLID;
683         } else if (!strcmp(groupValue, "3DFACE")) {
684            currentEntity = DL_ENTITY_3DFACE;
685         } else if (!strcmp(groupValue, "SEQEND")) {
686             currentEntity = DL_ENTITY_SEQEND;
687         } else {
688             currentEntity = DL_UNKNOWN;
689         }
690 
691 		// end of old style POLYLINE entity
692 		if (prevEntity==DL_ENTITY_VERTEX && currentEntity!=DL_ENTITY_VERTEX) {
693 			endEntity(creationInterface);
694 		}
695 
696         return true;
697 
698     } else {
699         // Group code does not indicate start of new entity or setting,
700         // so this group must be continuation of data for the current
701         // one.
702         if (groupCode<DL_DXF_MAXGROUPCODE) {
703 
704             bool handled = false;
705 
706             switch (currentEntity) {
707             case DL_ENTITY_MTEXT:
708                 handled = handleMTextData(creationInterface);
709                 break;
710 
711             case DL_ENTITY_LWPOLYLINE:
712                 handled = handleLWPolylineData(creationInterface);
713                 break;
714 
715             case DL_ENTITY_SPLINE:
716                 handled = handleSplineData(creationInterface);
717                 break;
718 
719             case DL_ENTITY_LEADER:
720                 handled = handleLeaderData(creationInterface);
721                 break;
722 
723             case DL_ENTITY_HATCH:
724                 handled = handleHatchData(creationInterface);
725                 break;
726 
727             default:
728                 break;
729             }
730 
731             if (!handled) {
732                 // Normal group / value pair:
733                 strncpy(values[groupCode], groupValue, DL_DXF_MAXLINE);
734                 values[groupCode][DL_DXF_MAXLINE] = '\0';
735             }
736         }
737 
738         return false;
739     }
740     return false;
741 }
742 
743 
744 
745 /**
746  * Adds a comment from the DXF file.
747  */
addComment(DL_CreationInterface * creationInterface,const char * comment)748 void DL_Dxf::addComment(DL_CreationInterface* creationInterface, const char* comment) {
749     creationInterface->addComment(comment);
750 }
751 
752 
753 
754 /**
755  * Adds a variable from the DXF file.
756  */
addSetting(DL_CreationInterface * creationInterface)757 void DL_Dxf::addSetting(DL_CreationInterface* creationInterface) {
758     int c = -1;
759     for (int i=0; i<=380; ++i) {
760         if (values[i][0]!='\0') {
761             c = i;
762             break;
763         }
764     }
765 
766     // string
767     if (c>=0 && c<=9) {
768         creationInterface->setVariableString(settingKey,
769                                              values[c], c);
770     }
771     // vector
772     else if (c>=10 && c<=39) {
773         if (c==10) {
774             creationInterface->setVariableVector(
775                 settingKey,
776                 toReal(values[c]),
777                 toReal(values[c+10]),
778                 toReal(values[c+20]),
779                 c);
780         }
781     }
782     // double
783     else if (c>=40 && c<=59) {
784         creationInterface->setVariableDouble(settingKey,
785                                              toReal(values[c]),
786                                              c);
787     }
788     // int
789     else if (c>=60 && c<=99) {
790         creationInterface->setVariableInt(settingKey,
791                                           toInt(values[c]),
792                                           c);
793     }
794     // misc
795     else if (c>=0) {
796         creationInterface->setVariableString(settingKey,
797                                              values[c],
798                                              c);
799     }
800 }
801 
802 
803 
804 /**
805  * Adds a layer that was read from the file via the creation interface.
806  */
addLayer(DL_CreationInterface * creationInterface)807 void DL_Dxf::addLayer(DL_CreationInterface* creationInterface) {
808     // correct some impossible attributes for layers:
809     attrib = creationInterface->getAttributes();
810     if (attrib.getColor()==256 || attrib.getColor()==0) {
811         attrib.setColor(7);
812     }
813     if (attrib.getWidth()<0) {
814         attrib.setWidth(1);
815     }
816     if (!strcasecmp(attrib.getLineType().c_str(), "BYLAYER") ||
817             !strcasecmp(attrib.getLineType().c_str(), "BYBLOCK")) {
818         attrib.setLineType("CONTINUOUS");
819     }
820 
821     // add layer
822     creationInterface->addLayer(DL_LayerData(values[2],
823                                 toInt(values[70])));
824 }
825 
826 
827 
828 /**
829  * Adds a block that was read from the file via the creation interface.
830  */
addBlock(DL_CreationInterface * creationInterface)831 void DL_Dxf::addBlock(DL_CreationInterface* creationInterface) {
832     DL_BlockData d(
833         // Name:
834         values[2],
835         // flags:
836         toInt(values[70]),
837         // base point:
838         toReal(values[10]),
839         toReal(values[20]),
840         toReal(values[30]));
841 
842     creationInterface->addBlock(d);
843 }
844 
845 
846 
847 /**
848  * Ends a block that was read from the file via the creation interface.
849  */
endBlock(DL_CreationInterface * creationInterface)850 void DL_Dxf::endBlock(DL_CreationInterface* creationInterface) {
851     creationInterface->endBlock();
852 }
853 
854 
855 
856 /**
857  * Adds a point entity that was read from the file via the creation interface.
858  */
addPoint(DL_CreationInterface * creationInterface)859 void DL_Dxf::addPoint(DL_CreationInterface* creationInterface) {
860     DL_PointData d(toReal(values[10]),
861                    toReal(values[20]),
862                    toReal(values[30]));
863     creationInterface->addPoint(d);
864 }
865 
866 
867 
868 /**
869  * Adds a line entity that was read from the file via the creation interface.
870  */
addLine(DL_CreationInterface * creationInterface)871 void DL_Dxf::addLine(DL_CreationInterface* creationInterface) {
872     DL_LineData d(toReal(values[10]),
873                   toReal(values[20]),
874                   toReal(values[30]),
875                   toReal(values[11]),
876                   toReal(values[21]),
877                   toReal(values[31]));
878 
879     creationInterface->addLine(d);
880 }
881 
882 
883 
884 /**
885  * Adds a polyline entity that was read from the file via the creation interface.
886  */
addPolyline(DL_CreationInterface * creationInterface)887 void DL_Dxf::addPolyline(DL_CreationInterface* creationInterface) {
888     DL_PolylineData pd(maxVertices, toInt(values[71], 0), toInt(values[72], 0), toInt(values[70], 0));
889     creationInterface->addPolyline(pd);
890 
891     if (currentEntity==DL_ENTITY_LWPOLYLINE) {
892         for (int i=0; i<maxVertices; i++) {
893             DL_VertexData d(vertices[i*4],
894                             vertices[i*4+1],
895                             vertices[i*4+2],
896                             vertices[i*4+3]);
897 
898             creationInterface->addVertex(d);
899         }
900 		creationInterface->endEntity();
901     }
902 }
903 
904 
905 
906 /**
907  * Adds a polyline vertex entity that was read from the file
908  * via the creation interface.
909  */
addVertex(DL_CreationInterface * creationInterface)910 void DL_Dxf::addVertex(DL_CreationInterface* creationInterface) {
911     DL_VertexData d(toReal(values[10]),
912                     toReal(values[20]),
913                     toReal(values[30]),
914                     //bulge);
915                     toReal(values[42]));
916 
917     //bulge = toReal(values[42]);
918 
919     creationInterface->addVertex(d);
920 }
921 
922 
923 
924 /**
925  * Adds a spline entity that was read from the file via the creation interface.
926  */
addSpline(DL_CreationInterface * creationInterface)927 void DL_Dxf::addSpline(DL_CreationInterface* creationInterface) {
928     DL_SplineData sd(toInt(values[71], 3),
929                      maxKnots,
930                      maxControlPoints,
931                      toInt(values[70], 4));
932     /*DL_SplineData sd(toInt(values[71], 3), toInt(values[72], 0),
933                      toInt(values[73], 0), toInt(values[70], 4));*/
934     creationInterface->addSpline(sd);
935 
936     int i;
937     for (i=0; i<maxControlPoints; i++) {
938         DL_ControlPointData d(controlPoints[i*3],
939                               controlPoints[i*3+1],
940                               controlPoints[i*3+2]);
941 
942         creationInterface->addControlPoint(d);
943     }
944     for (i=0; i<maxKnots; i++) {
945       DL_KnotData k(knots[i]);
946 
947       creationInterface->addKnot(k);
948     }
949 }
950 
951 
952 
953 /**
954  * Adds an arc entity that was read from the file via the creation interface.
955  */
addArc(DL_CreationInterface * creationInterface)956 void DL_Dxf::addArc(DL_CreationInterface* creationInterface) {
957     DL_ArcData d(toReal(values[10]),
958                  toReal(values[20]),
959                  toReal(values[30]),
960                  toReal(values[40]),
961                  toReal(values[50]),
962                  toReal(values[51]));
963 
964     creationInterface->addArc(d);
965 }
966 
967 
968 
969 /**
970  * Adds a circle entity that was read from the file via the creation interface.
971  */
addCircle(DL_CreationInterface * creationInterface)972 void DL_Dxf::addCircle(DL_CreationInterface* creationInterface) {
973     DL_CircleData d(toReal(values[10]),
974                     toReal(values[20]),
975                     toReal(values[30]),
976                     toReal(values[40]));
977 
978     creationInterface->addCircle(d);
979 }
980 
981 
982 
983 /**
984  * Adds an ellipse entity that was read from the file via the creation interface.
985  */
addEllipse(DL_CreationInterface * creationInterface)986 void DL_Dxf::addEllipse(DL_CreationInterface* creationInterface) {
987     DL_EllipseData d(toReal(values[10]),
988                      toReal(values[20]),
989                      toReal(values[30]),
990                      toReal(values[11]),
991                      toReal(values[21]),
992                      toReal(values[31]),
993                      toReal(values[40], 1.0),
994                      toReal(values[41], 0.0),
995                      toReal(values[42], 2*M_PI));
996 
997     creationInterface->addEllipse(d);
998 }
999 
1000 
1001 
1002 /**
1003  * Adds an insert entity that was read from the file via the creation interface.
1004  */
addInsert(DL_CreationInterface * creationInterface)1005 void DL_Dxf::addInsert(DL_CreationInterface* creationInterface) {
1006     DL_InsertData d(values[2],
1007                     // insertion point
1008                     toReal(values[10], 0.0),
1009                     toReal(values[20], 0.0),
1010                     toReal(values[30], 0.0),
1011                     // scale:
1012                     toReal(values[41], 1.0),
1013                     toReal(values[42], 1.0),
1014                     toReal(values[43], 1.0),
1015                     // angle:
1016                     toReal(values[50], 0.0),
1017                     // cols / rows:
1018                     toInt(values[70], 1),
1019                     toInt(values[71], 1),
1020                     // spacing:
1021                     toReal(values[44], 0.0),
1022                     toReal(values[45], 0.0));
1023 
1024     creationInterface->addInsert(d);
1025 }
1026 
1027 
1028 
1029 /**
1030  * Adds a trace entity (4 edge closed polyline) that was read from the file via the creation interface.
1031  *
1032  * @author AHM
1033  */
addTrace(DL_CreationInterface * creationInterface)1034 void DL_Dxf::addTrace(DL_CreationInterface* creationInterface) {
1035     DL_TraceData td;
1036 
1037     for (int k = 0; k < 4; k++) {
1038        td.x[k] = toReal(values[10 + k]);
1039        td.y[k] = toReal(values[20 + k]);
1040        td.z[k] = toReal(values[30 + k]);
1041     }
1042     creationInterface->addTrace(td);
1043 }
1044 
1045 
1046 
1047 /**
1048  * Adds a 3dface entity that was read from the file via the creation interface.
1049  */
add3dFace(DL_CreationInterface * creationInterface)1050 void DL_Dxf::add3dFace(DL_CreationInterface* creationInterface) {
1051     DL_3dFaceData td;
1052 
1053     for (int k = 0; k < 4; k++) {
1054        td.x[k] = toReal(values[10 + k]);
1055        td.y[k] = toReal(values[20 + k]);
1056        td.z[k] = toReal(values[30 + k]);
1057     }
1058     creationInterface->add3dFace(td);
1059 }
1060 
1061 
1062 
1063 /**
1064  * Adds a solid entity (filled trace) that was read from the file via the creation interface.
1065  *
1066  * @author AHM
1067  */
addSolid(DL_CreationInterface * creationInterface)1068 void DL_Dxf::addSolid(DL_CreationInterface* creationInterface) {
1069     DL_SolidData sd;
1070 
1071     for (int k = 0; k < 4; k++) {
1072        sd.x[k] = toReal(values[10 + k]);
1073        sd.y[k] = toReal(values[20 + k]);
1074        sd.z[k] = toReal(values[30 + k]);
1075     }
1076     creationInterface->addSolid(sd);
1077 }
1078 
1079 
1080 /**
1081  * Adds an MText entity that was read from the file via the creation interface.
1082  */
addMText(DL_CreationInterface * creationInterface)1083 void DL_Dxf::addMText(DL_CreationInterface* creationInterface) {
1084     double angle = 0.0;
1085 
1086     if (values[50][0]!='\0') {
1087         if (libVersion<=0x02000200) {
1088             // wrong but compatible with dxflib <=2.0.2.0:
1089             angle = toReal(values[50], 0.0);
1090         } else {
1091             angle = (toReal(values[50], 0.0)*2*M_PI)/360.0;
1092         }
1093     } else if (values[11][0]!='\0' && values[21][0]!='\0') {
1094         double x = toReal(values[11], 0.0);
1095         double y = toReal(values[21], 0.0);
1096 
1097         if (fabs(x)<1.0e-6) {
1098             if (y>0.0) {
1099                 angle = M_PI/2.0;
1100             } else {
1101                 angle = M_PI/2.0*3.0;
1102             }
1103         } else {
1104             angle = atan(y/x);
1105         }
1106     }
1107 
1108     DL_MTextData d(
1109         // insertion point
1110         toReal(values[10], 0.0),
1111         toReal(values[20], 0.0),
1112         toReal(values[30], 0.0),
1113         // height
1114         toReal(values[40], 2.5),
1115         // width
1116         toReal(values[41], 100.0),
1117         // attachment point
1118         toInt(values[71], 1),
1119         // drawing direction
1120         toInt(values[72], 1),
1121         // line spacing style
1122         toInt(values[73], 1),
1123         // line spacing factor
1124         toReal(values[44], 1.0),
1125         // text
1126         values[1],
1127         // style
1128         values[7],
1129         // angle
1130         angle);
1131     creationInterface->addMText(d);
1132 }
1133 
1134 
1135 
1136 /**
1137  * Handles additional MText data.
1138  */
handleMTextData(DL_CreationInterface * creationInterface)1139 bool DL_Dxf::handleMTextData(DL_CreationInterface* creationInterface) {
1140     // Special handling of text chunks for MTEXT entities:
1141     if (groupCode==3) {
1142         creationInterface->addMTextChunk(groupValue);
1143         return true;
1144     }
1145 
1146     return false;
1147 }
1148 
1149 
1150 
1151 /**
1152  * Handles additional polyline data.
1153  */
handleLWPolylineData(DL_CreationInterface *)1154 bool DL_Dxf::handleLWPolylineData(DL_CreationInterface* /*creationInterface*/) {
1155     // Allocate LWPolyline vertices (group code 90):
1156     if (groupCode==90) {
1157         maxVertices = toInt(groupValue);
1158         if (maxVertices>0) {
1159             if (vertices!=NULL) {
1160                 delete[] vertices;
1161             }
1162             vertices = new double[4*maxVertices];
1163             for (int i=0; i<maxVertices; ++i) {
1164                 vertices[i*4] = 0.0;
1165                 vertices[i*4+1] = 0.0;
1166                 vertices[i*4+2] = 0.0;
1167                 vertices[i*4+3] = 0.0;
1168             }
1169         }
1170         vertexIndex=-1;
1171         return true;
1172     }
1173 
1174     // Compute LWPolylines vertices (group codes 10/20/30/42):
1175     else if (groupCode==10 || groupCode==20 ||
1176              groupCode==30 || groupCode==42) {
1177 
1178         if (vertexIndex<maxVertices-1 && groupCode==10) {
1179             vertexIndex++;
1180         }
1181 
1182         if (groupCode<=30) {
1183             if (vertexIndex>=0 && vertexIndex<maxVertices) {
1184                 vertices[4*vertexIndex + (groupCode/10-1)]
1185                 = toReal(groupValue);
1186             }
1187         } else if (groupCode==42 && vertexIndex<maxVertices) {
1188             vertices[4*vertexIndex + 3] = toReal(groupValue);
1189         }
1190         return true;
1191     }
1192     return false;
1193 }
1194 
1195 
1196 
1197 /**
1198  * Handles additional spline data.
1199  */
handleSplineData(DL_CreationInterface *)1200 bool DL_Dxf::handleSplineData(DL_CreationInterface* /*creationInterface*/) {
1201     // Allocate Spline knots (group code 72):
1202     if (groupCode==72) {
1203         maxKnots = toInt(groupValue);
1204         if (maxKnots>0) {
1205             if (knots!=NULL) {
1206                 delete[] knots;
1207             }
1208             knots = new double[maxKnots];
1209             for (int i=0; i<maxKnots; ++i) {
1210                 knots[i] = 0.0;
1211             }
1212         }
1213         knotIndex=-1;
1214         return true;
1215     }
1216 
1217     // Allocate Spline control points (group code 73):
1218     else if (groupCode==73) {
1219         maxControlPoints = toInt(groupValue);
1220         if (maxControlPoints>0) {
1221             if (controlPoints!=NULL) {
1222                 delete[] controlPoints;
1223             }
1224             controlPoints = new double[3*maxControlPoints];
1225             for (int i=0; i<maxControlPoints; ++i) {
1226                 controlPoints[i*3] = 0.0;
1227                 controlPoints[i*3+1] = 0.0;
1228                 controlPoints[i*3+2] = 0.0;
1229             }
1230         }
1231         controlPointIndex=-1;
1232         return true;
1233     }
1234 
1235     // Compute spline knot vertices (group code 40):
1236     else if (groupCode==40) {
1237         if (knotIndex<maxKnots-1) {
1238             knotIndex++;
1239             knots[knotIndex] = toReal(groupValue);
1240         }
1241         return true;
1242     }
1243 
1244     // Compute spline control points (group codes 10/20/30):
1245     else if (groupCode==10 || groupCode==20 ||
1246              groupCode==30) {
1247 
1248         if (controlPointIndex<maxControlPoints-1 && groupCode==10) {
1249             controlPointIndex++;
1250         }
1251 
1252         if (controlPointIndex>=0 && controlPointIndex<maxControlPoints) {
1253             controlPoints[3*controlPointIndex + (groupCode/10-1)]
1254             = toReal(groupValue);
1255         }
1256         return true;
1257     }
1258     return false;
1259 }
1260 
1261 
1262 
1263 /**
1264  * Handles additional leader data.
1265  */
handleLeaderData(DL_CreationInterface *)1266 bool DL_Dxf::handleLeaderData(DL_CreationInterface* /*creationInterface*/) {
1267     // Allocate Leader vertices (group code 76):
1268     if (groupCode==76) {
1269         maxLeaderVertices = toInt(groupValue);
1270         if (maxLeaderVertices>0) {
1271             if (leaderVertices!=NULL) {
1272                 delete[] leaderVertices;
1273             }
1274             leaderVertices = new double[3*maxLeaderVertices];
1275             for (int i=0; i<maxLeaderVertices; ++i) {
1276                 leaderVertices[i*3] = 0.0;
1277                 leaderVertices[i*3+1] = 0.0;
1278                 leaderVertices[i*3+2] = 0.0;
1279             }
1280         }
1281         leaderVertexIndex=-1;
1282         return true;
1283     }
1284 
1285     // Compute Leader vertices (group codes 10/20/30):
1286     else if (groupCode==10 || groupCode==20 || groupCode==30) {
1287 
1288         if (leaderVertexIndex<maxLeaderVertices-1 && groupCode==10) {
1289             leaderVertexIndex++;
1290         }
1291 
1292         if (groupCode<=30) {
1293             if (leaderVertexIndex>=0 &&
1294                     leaderVertexIndex<maxLeaderVertices) {
1295                 leaderVertices[3*leaderVertexIndex + (groupCode/10-1)]
1296                 = toReal(groupValue);
1297             }
1298         }
1299         return true;
1300     }
1301 
1302     return false;
1303 }
1304 
1305 
1306 
1307 /**
1308  * Handles additional hatch data.
1309  */
handleHatchData(DL_CreationInterface *)1310 bool DL_Dxf::handleHatchData(DL_CreationInterface* /*creationInterface*/) {
1311 
1312     static int firstPolylineStatus = 0;
1313 
1314     // Allocate hatch loops (group code 91):
1315     if (groupCode==91 && toInt(groupValue)>0) {
1316 
1317         if (hatchLoops!=NULL) {
1318             delete[] hatchLoops;
1319             hatchLoops = NULL;
1320         }
1321         if (maxHatchEdges!=NULL) {
1322             delete[] maxHatchEdges;
1323             maxHatchEdges = NULL;
1324         }
1325         if (hatchEdgeIndex!=NULL) {
1326             delete[] hatchEdgeIndex;
1327             hatchEdgeIndex = NULL;
1328         }
1329         if (hatchEdges!=NULL) {
1330             for (int i=0; i<maxHatchLoops; ++i) {
1331                 delete[] hatchEdges[i];
1332             }
1333             delete[] hatchEdges;
1334             hatchEdges = NULL;
1335         }
1336         maxHatchLoops = toInt(groupValue);
1337 
1338         if (maxHatchLoops>0) {
1339             hatchLoops = new DL_HatchLoopData[maxHatchLoops];
1340             maxHatchEdges = new int[maxHatchLoops];
1341             hatchEdgeIndex = new int[maxHatchLoops];
1342             hatchEdges = new DL_HatchEdgeData*[maxHatchLoops];
1343             for (int i=0; i<maxHatchLoops; ++i) {
1344                 hatchEdges[i] = NULL;
1345                 maxHatchEdges[i] = 0;
1346             }
1347             hatchLoopIndex = -1;
1348             dropEdges = false;
1349         }
1350         return true;
1351     }
1352 
1353     // Allocate hatch edges, group code 93
1354     if (groupCode==93 && toInt(groupValue)>0) {
1355         if (hatchLoopIndex<maxHatchLoops-1 && hatchLoops!=NULL &&
1356                 maxHatchEdges!=NULL && hatchEdgeIndex!=NULL &&
1357                 hatchEdges!=NULL) {
1358 
1359             dropEdges = false;
1360 
1361             hatchLoopIndex++;
1362             hatchLoops[hatchLoopIndex]
1363             = DL_HatchLoopData(toInt(groupValue));
1364 
1365             maxHatchEdges[hatchLoopIndex] = toInt(groupValue);
1366             hatchEdgeIndex[hatchLoopIndex] = -1;
1367             hatchEdges[hatchLoopIndex]
1368                 = new DL_HatchEdgeData[toInt(groupValue)];
1369             firstPolylineStatus = 0;
1370         } else {
1371             dropEdges = true;
1372         }
1373         return true;
1374     }
1375 
1376     // Init hatch edge for non-polyline boundary (group code 72)
1377     if (hatchEdges!=NULL &&
1378             hatchEdgeIndex!=NULL &&
1379             maxHatchEdges!=NULL &&
1380             hatchLoopIndex>=0 &&
1381             hatchLoopIndex<maxHatchLoops &&
1382             hatchEdgeIndex[hatchLoopIndex] <
1383             maxHatchEdges[hatchLoopIndex] &&
1384             (atoi(values[92])&2)==0 &&   // not a polyline
1385             groupCode==72 &&
1386             !dropEdges) {
1387 
1388         hatchEdgeIndex[hatchLoopIndex]++;
1389 
1390         hatchEdges[hatchLoopIndex][hatchEdgeIndex[hatchLoopIndex]]
1391         .type = toInt(groupValue);
1392         hatchEdges[hatchLoopIndex][hatchEdgeIndex[hatchLoopIndex]]
1393         .defined = false;
1394 
1395         return true;
1396     }
1397 
1398     // Handle hatch edges for non-polyline boundaries
1399     //   (group codes 10, 20, 11, 21, 40, 50, 51, 73)
1400     if (!dropEdges &&
1401             hatchEdges!=NULL &&
1402             hatchEdgeIndex!=NULL &&
1403             hatchLoopIndex>=0 &&
1404             hatchLoopIndex<maxHatchLoops &&
1405             hatchEdges[hatchLoopIndex]!=NULL &&
1406             hatchEdgeIndex[hatchLoopIndex]>=0 &&
1407             hatchEdgeIndex[hatchLoopIndex] <
1408             maxHatchEdges[hatchLoopIndex] &&
1409             ((atoi(values[92])&2)==0) &&        // not a polyline
1410             (groupCode==10 || groupCode==20 ||
1411              groupCode==11 || groupCode==21 ||
1412              groupCode==40 || groupCode==50 ||
1413              groupCode==51 || groupCode==73)) {
1414 
1415         if (hatchEdges[hatchLoopIndex]
1416                 [hatchEdgeIndex[hatchLoopIndex]].defined==false) {
1417             if (hatchEdges[hatchLoopIndex]
1418                     [hatchEdgeIndex[hatchLoopIndex]].type==1) {
1419                 switch (groupCode) {
1420                 case 10:
1421                     hatchEdges[hatchLoopIndex]
1422                     [hatchEdgeIndex[hatchLoopIndex]].x1
1423                     = toReal(groupValue);
1424                     break;
1425                 case 20:
1426                     hatchEdges[hatchLoopIndex]
1427                     [hatchEdgeIndex[hatchLoopIndex]].y1
1428                     = toReal(groupValue);
1429                     break;
1430                 case 11:
1431                     hatchEdges[hatchLoopIndex]
1432                     [hatchEdgeIndex[hatchLoopIndex]].x2
1433                     = toReal(groupValue);
1434                     break;
1435                 case 21:
1436                     hatchEdges[hatchLoopIndex]
1437                     [hatchEdgeIndex[hatchLoopIndex]].y2
1438                     = toReal(groupValue);
1439                     hatchEdges[hatchLoopIndex]
1440                     [hatchEdgeIndex[hatchLoopIndex]].defined = true;
1441                     break;
1442                 default:
1443                     break;
1444                 }
1445             }
1446 
1447             if (hatchEdges[hatchLoopIndex]
1448                     [hatchEdgeIndex[hatchLoopIndex]].type==2) {
1449                 switch (groupCode) {
1450                 case 10:
1451                     hatchEdges[hatchLoopIndex]
1452                     [hatchEdgeIndex[hatchLoopIndex]].cx
1453                     = toReal(groupValue);
1454                     break;
1455                 case 20:
1456                     hatchEdges[hatchLoopIndex]
1457                     [hatchEdgeIndex[hatchLoopIndex]].cy
1458                     = toReal(groupValue);
1459                     break;
1460                 case 40:
1461                     hatchEdges[hatchLoopIndex]
1462                     [hatchEdgeIndex[hatchLoopIndex]].radius
1463                     = toReal(groupValue);
1464                     break;
1465                 case 50:
1466                     hatchEdges[hatchLoopIndex]
1467                     [hatchEdgeIndex[hatchLoopIndex]].angle1
1468                     = toReal(groupValue)/360.0*2*M_PI;
1469                     break;
1470                 case 51:
1471                     hatchEdges[hatchLoopIndex]
1472                     [hatchEdgeIndex[hatchLoopIndex]].angle2
1473                     = toReal(groupValue)/360.0*2*M_PI;
1474                     break;
1475                 case 73:
1476                     hatchEdges[hatchLoopIndex]
1477                     [hatchEdgeIndex[hatchLoopIndex]].ccw
1478                     = (bool)toInt(groupValue);
1479                     hatchEdges[hatchLoopIndex]
1480                     [hatchEdgeIndex[hatchLoopIndex]].defined = true;
1481                     break;
1482                 default:
1483                     break;
1484                 }
1485             }
1486         }
1487         return true;
1488     }
1489 
1490     /*
1491     // 2003/12/31: polyline hatches can be extremely slow and are rarely used
1492     //
1493        // Handle hatch edges for polyline boundaries
1494        //  (group codes 10, 20, 42)
1495        if (!dropEdges &&
1496                hatchEdges!=NULL &&
1497                hatchEdgeIndex!=NULL &&
1498                hatchLoopIndex>=0 &&
1499                hatchLoopIndex<maxHatchLoops &&
1500                hatchEdges[hatchLoopIndex]!=NULL &&
1501                //hatchEdgeIndex[hatchLoopIndex]>=0 &&
1502                hatchEdgeIndex[hatchLoopIndex] <
1503                maxHatchEdges[hatchLoopIndex] &&
1504                ((atoi(values[92])&2)==2)) {        // a polyline
1505 
1506            if (groupCode==10 || groupCode==20 ||
1507                    groupCode==42) {
1508 
1509                std::cout << "  found polyline edge data: " << groupCode << "\n";
1510                std::cout << "     value: " << toReal(groupValue) << "\n";
1511 
1512                static double lastX = 0.0;
1513                static double lastY = 0.0;
1514                static double lastB = 0.0;
1515 
1516                if (firstPolylineStatus<2) {
1517                    switch (groupCode) {
1518                    case 10:
1519                        firstPolylineStatus++;
1520                        if (firstPolylineStatus==1) {
1521                            lastX = toReal(groupValue);
1522                            std::cout << "     firstX: " << lastX << "\n";
1523                        }
1524                        break;
1525 
1526                    case 20:
1527                        lastY = toReal(groupValue);
1528                        std::cout << "     firstY: " << lastY << "\n";
1529                        break;
1530 
1531                    case 42:
1532                        lastB = toReal(groupValue);
1533                        break;
1534 
1535                    default:
1536                        break;
1537                    }
1538 
1539                    if (firstPolylineStatus!=2) {
1540                        return true;
1541                    }
1542                }
1543 
1544 
1545                switch (groupCode) {
1546                case 10:
1547                    hatchEdgeIndex[hatchLoopIndex]++;
1548                    hatchEdges[hatchLoopIndex]
1549                    [hatchEdgeIndex[hatchLoopIndex]].type = 1;
1550                    hatchEdges[hatchLoopIndex]
1551                    [hatchEdgeIndex[hatchLoopIndex]].x1
1552                    = lastX;
1553                    hatchEdges[hatchLoopIndex]
1554                    [hatchEdgeIndex[hatchLoopIndex]].x2
1555                    = lastX = toReal(groupValue);
1556                    std::cout << "     X: " << lastX << "\n";
1557                    break;
1558                case 20:
1559                    hatchEdges[hatchLoopIndex]
1560                    [hatchEdgeIndex[hatchLoopIndex]].y1
1561                    = lastY;
1562                    hatchEdges[hatchLoopIndex]
1563                    [hatchEdgeIndex[hatchLoopIndex]].y2
1564                    = lastY = toReal(groupValue);
1565                    std::cout << "     Y: " << lastY << "\n";
1566                    break;
1567                    / *
1568                                case 42: {
1569                    	// convert to arc:
1570                    	double x1 = hatchEdges[hatchLoopIndex]
1571                    		[hatchEdgeIndex[hatchLoopIndex]].x1;
1572                    	double y1 = hatchEdges[hatchLoopIndex]
1573                    		[hatchEdgeIndex[hatchLoopIndex]].y1;
1574                    	double x2 = hatchEdges[hatchLoopIndex]
1575                    		[hatchEdgeIndex[hatchLoopIndex]].x2;
1576                    	double y2 = hatchEdges[hatchLoopIndex]
1577                    		[hatchEdgeIndex[hatchLoopIndex]].y2;
1578 
1579                    	double bulge = toReal(groupValue);
1580 
1581                    	bool reversed = (bulge<0.0);
1582                    	double alpha = atan(bulge)*4.0;
1583                    	double radius;
1584                              double cx;
1585                              double cy;
1586                    	double a1;
1587                    	double a2;
1588                              double mx = (x2+x1)/2.0;
1589                              double my = (y2+y1)/2.0;
1590                    	double dist = sqrt(pow(x2-x1,2) + pow(y2-y1,2)) / 2.0;
1591 
1592                    	// alpha can't be 0.0 at this point
1593                              radius = fabs(dist / sin(alpha/2.0));
1594 
1595                              double wu = fabs(pow(radius, 2.0) - pow(dist, 2.0));
1596                              double h = sqrt(wu);
1597                    	double angle = acos((x2-x1) / dist);
1598 
1599                              if (bulge>0.0) {
1600                        		        angle+=M_PI/2.0;
1601                              } else {
1602                                  angle-=M_PI/2.0;
1603                              }
1604 
1605                              if (fabs(alpha)>M_PI) {
1606                                  h*=-1.0;
1607                              }
1608 
1609                    	cx = mx + cos(angle) * h;
1610                    	cy = my + sin(angle) * h;
1611 
1612                    	a1 = hatchEdges[hatchLoopIndex]
1613                                    	[hatchEdgeIndex[hatchLoopIndex]].type = 2;
1614                                    hatchEdges[hatchLoopIndex]
1615                                    	[hatchEdgeIndex[hatchLoopIndex]].ccw = (toReal(groupValue)>0.0);
1616                                    hatchEdges[hatchLoopIndex]
1617                                    	[hatchEdgeIndex[hatchLoopIndex]].cx = cx;
1618                                    hatchEdges[hatchLoopIndex]
1619                                    	[hatchEdgeIndex[hatchLoopIndex]].cy = cy;
1620                                    hatchEdges[hatchLoopIndex]
1621                                    	[hatchEdgeIndex[hatchLoopIndex]].radius = radius;
1622                                    } break;
1623                    	* /
1624 
1625                default:
1626                    break;
1627                }
1628            } else {
1629                // end polyline boundary
1630                dropEdges = true;
1631            }
1632 
1633            return true;
1634        }
1635     */
1636 
1637     return false;
1638 }
1639 
1640 
1641 
1642 
1643 /**
1644  * Adds an text entity that was read from the file via the creation interface.
1645  */
addText(DL_CreationInterface * creationInterface)1646 void DL_Dxf::addText(DL_CreationInterface* creationInterface) {
1647     DL_TextData d(
1648         // insertion point
1649         toReal(values[10], 0.0),
1650         toReal(values[20], 0.0),
1651         toReal(values[30], 0.0),
1652         // alignment point
1653         toReal(values[11], 0.0),
1654         toReal(values[21], 0.0),
1655         toReal(values[31], 0.0),
1656         // height
1657         toReal(values[40], 2.5),
1658         // x scale
1659         toReal(values[41], 1.0),
1660         // generation flags
1661         toInt(values[71], 0),
1662         // h just
1663         toInt(values[72], 0),
1664         // v just
1665         toInt(values[73], 0),
1666         // text
1667         values[1],
1668         // style
1669         values[7],
1670         // angle
1671         (toReal(values[50], 0.0)*2*M_PI)/360.0);
1672 
1673     creationInterface->addText(d);
1674 }
1675 
1676 
1677 
1678 /**
1679  * Adds an attrib entity that was read from the file via the creation interface.
1680  * @todo add attrib instead of normal text
1681  */
addAttrib(DL_CreationInterface * creationInterface)1682 void DL_Dxf::addAttrib(DL_CreationInterface* creationInterface) {
1683     DL_TextData d(
1684         // insertion point
1685         toReal(values[10], 0.0),
1686         toReal(values[20], 0.0),
1687         toReal(values[30], 0.0),
1688         // alignment point
1689         toReal(values[11], 0.0),
1690         toReal(values[21], 0.0),
1691         toReal(values[31], 0.0),
1692         // height
1693         toReal(values[40], 2.5),
1694         // x scale
1695         toReal(values[41], 1.0),
1696         // generation flags
1697         toInt(values[71], 0),
1698         // h just
1699         toInt(values[72], 0),
1700         // v just
1701         toInt(values[74], 0),
1702         // text
1703         values[1],
1704         // style
1705         values[7],
1706         // angle
1707         (toReal(values[50], 0.0)*2*M_PI)/360.0);
1708 
1709     creationInterface->addText(d);
1710 }
1711 
1712 
1713 
1714 /**
1715  * @return dimension data from current values.
1716  */
getDimData()1717 DL_DimensionData DL_Dxf::getDimData() {
1718     // generic dimension data:
1719     return DL_DimensionData(
1720                // def point
1721                toReal(values[10], 0.0),
1722                toReal(values[20], 0.0),
1723                toReal(values[30], 0.0),
1724                // text middle point
1725                toReal(values[11], 0.0),
1726                toReal(values[21], 0.0),
1727                toReal(values[31], 0.0),
1728                // type
1729                toInt(values[70], 0),
1730                // attachment point
1731                toInt(values[71], 5),
1732                // line sp. style
1733                toInt(values[72], 1),
1734                // line sp. factor
1735                toReal(values[41], 1.0),
1736                // text
1737                values[1],
1738                // style
1739                values[3],
1740                // angle
1741                toReal(values[53], 0.0));
1742 }
1743 
1744 
1745 
1746 /**
1747  * Adds a linear dimension entity that was read from the file via the creation interface.
1748  */
addDimLinear(DL_CreationInterface * creationInterface)1749 void DL_Dxf::addDimLinear(DL_CreationInterface* creationInterface) {
1750     DL_DimensionData d = getDimData();
1751 
1752     // horizontal / vertical / rotated dimension:
1753     DL_DimLinearData dl(
1754         // definition point 1
1755         toReal(values[13], 0.0),
1756         toReal(values[23], 0.0),
1757         toReal(values[33], 0.0),
1758         // definition point 2
1759         toReal(values[14], 0.0),
1760         toReal(values[24], 0.0),
1761         toReal(values[34], 0.0),
1762         // angle
1763         toReal(values[50], 0.0),
1764         // oblique
1765         toReal(values[52], 0.0));
1766     creationInterface->addDimLinear(d, dl);
1767 }
1768 
1769 
1770 
1771 /**
1772  * Adds an aligned dimension entity that was read from the file via the creation interface.
1773  */
addDimAligned(DL_CreationInterface * creationInterface)1774 void DL_Dxf::addDimAligned(DL_CreationInterface* creationInterface) {
1775     DL_DimensionData d = getDimData();
1776 
1777     // aligned dimension:
1778     DL_DimAlignedData da(
1779         // extension point 1
1780         toReal(values[13], 0.0),
1781         toReal(values[23], 0.0),
1782         toReal(values[33], 0.0),
1783         // extension point 2
1784         toReal(values[14], 0.0),
1785         toReal(values[24], 0.0),
1786         toReal(values[34], 0.0));
1787     creationInterface->addDimAlign(d, da);
1788 }
1789 
1790 
1791 
1792 /**
1793  * Adds a radial dimension entity that was read from the file via the creation interface.
1794  */
addDimRadial(DL_CreationInterface * creationInterface)1795 void DL_Dxf::addDimRadial(DL_CreationInterface* creationInterface) {
1796     DL_DimensionData d = getDimData();
1797 
1798     DL_DimRadialData dr(
1799         // definition point
1800         toReal(values[15], 0.0),
1801         toReal(values[25], 0.0),
1802         toReal(values[35], 0.0),
1803         // leader length:
1804         toReal(values[40], 0.0));
1805     creationInterface->addDimRadial(d, dr);
1806 }
1807 
1808 
1809 
1810 /**
1811  * Adds a diametric dimension entity that was read from the file via the creation interface.
1812  */
addDimDiametric(DL_CreationInterface * creationInterface)1813 void DL_Dxf::addDimDiametric(DL_CreationInterface* creationInterface) {
1814     DL_DimensionData d = getDimData();
1815 
1816     // diametric dimension:
1817     DL_DimDiametricData dr(
1818         // definition point
1819         toReal(values[15], 0.0),
1820         toReal(values[25], 0.0),
1821         toReal(values[35], 0.0),
1822         // leader length:
1823         toReal(values[40], 0.0));
1824     creationInterface->addDimDiametric(d, dr);
1825 }
1826 
1827 
1828 
1829 /**
1830  * Adds an angular dimension entity that was read from the file via the creation interface.
1831  */
addDimAngular(DL_CreationInterface * creationInterface)1832 void DL_Dxf::addDimAngular(DL_CreationInterface* creationInterface) {
1833     DL_DimensionData d = getDimData();
1834 
1835     // angular dimension:
1836     DL_DimAngularData da(
1837         // definition point 1
1838         toReal(values[13], 0.0),
1839         toReal(values[23], 0.0),
1840         toReal(values[33], 0.0),
1841         // definition point 2
1842         toReal(values[14], 0.0),
1843         toReal(values[24], 0.0),
1844         toReal(values[34], 0.0),
1845         // definition point 3
1846         toReal(values[15], 0.0),
1847         toReal(values[25], 0.0),
1848         toReal(values[35], 0.0),
1849         // definition point 4
1850         toReal(values[16], 0.0),
1851         toReal(values[26], 0.0),
1852         toReal(values[36], 0.0));
1853     creationInterface->addDimAngular(d, da);
1854 }
1855 
1856 
1857 /**
1858  * Adds an angular dimension entity that was read from the file via the creation interface.
1859  */
addDimAngular3P(DL_CreationInterface * creationInterface)1860 void DL_Dxf::addDimAngular3P(DL_CreationInterface* creationInterface) {
1861     DL_DimensionData d = getDimData();
1862 
1863     // angular dimension (3P):
1864     DL_DimAngular3PData da(
1865         // definition point 1
1866         toReal(values[13], 0.0),
1867         toReal(values[23], 0.0),
1868         toReal(values[33], 0.0),
1869         // definition point 2
1870         toReal(values[14], 0.0),
1871         toReal(values[24], 0.0),
1872         toReal(values[34], 0.0),
1873         // definition point 3
1874         toReal(values[15], 0.0),
1875         toReal(values[25], 0.0),
1876         toReal(values[35], 0.0));
1877     creationInterface->addDimAngular3P(d, da);
1878 }
1879 
1880 
1881 
1882 /**
1883  * Adds an ordinate dimension entity that was read from the file via the creation interface.
1884  */
addDimOrdinate(DL_CreationInterface * creationInterface)1885 void DL_Dxf::addDimOrdinate(DL_CreationInterface* creationInterface) {
1886     DL_DimensionData d = getDimData();
1887 
1888     // ordinate dimension:
1889     DL_DimOrdinateData dl(
1890         // definition point 1
1891         toReal(values[13], 0.0),
1892         toReal(values[23], 0.0),
1893         toReal(values[33], 0.0),
1894         // definition point 2
1895         toReal(values[14], 0.0),
1896         toReal(values[24], 0.0),
1897         toReal(values[34], 0.0),
1898         (toInt(values[70])&64)==64         // true: X-type, false: Y-type
1899     );
1900     creationInterface->addDimOrdinate(d, dl);
1901 }
1902 
1903 
1904 
1905 /**
1906  * Adds a leader entity that was read from the file via the creation interface.
1907  */
addLeader(DL_CreationInterface * creationInterface)1908 void DL_Dxf::addLeader(DL_CreationInterface* creationInterface) {
1909     // leader (arrow)
1910     DL_LeaderData le(
1911         // arrow head flag
1912         toInt(values[71], 1),
1913         // leader path type
1914         toInt(values[72], 0),
1915         // Leader creation flag
1916         toInt(values[73], 3),
1917         // Hookline direction flag
1918         toInt(values[74], 1),
1919         // Hookline flag
1920         toInt(values[75], 0),
1921         // Text annotation height
1922         toReal(values[40], 1.0),
1923         // Text annotation width
1924         toReal(values[41], 1.0),
1925         // Number of vertices in leader
1926         toInt(values[76], 0)
1927     );
1928     creationInterface->addLeader(le);
1929 
1930     for (int i=0; i<maxLeaderVertices; i++) {
1931         DL_LeaderVertexData d(leaderVertices[i*3],
1932                               leaderVertices[i*3+1],
1933                               leaderVertices[i*3+2]);
1934 
1935         creationInterface->addLeaderVertex(d);
1936     }
1937 }
1938 
1939 
1940 
1941 /**
1942  * Adds a hatch entity that was read from the file via the creation interface.
1943  */
addHatch(DL_CreationInterface * creationInterface)1944 void DL_Dxf::addHatch(DL_CreationInterface* creationInterface) {
1945     DL_HatchData hd(toInt(values[91], 1),
1946                     toInt(values[70], 0),
1947                     toReal(values[41], 1.0),
1948                     toReal(values[52], 0.0),
1949                     values[2]);
1950     creationInterface->addHatch(hd);
1951 
1952     for (int l=0; l<maxHatchLoops; l++) {
1953         DL_HatchLoopData ld(maxHatchEdges[l]);
1954         creationInterface->addHatchLoop(ld);
1955         for (int b=0; b<maxHatchEdges[l]; b++) {
1956             creationInterface->addHatchEdge(hatchEdges[l][b]);
1957         }
1958     }
1959     creationInterface->endEntity();
1960     currentEntity = DL_UNKNOWN;
1961 }
1962 
1963 
1964 
1965 /**
1966  * Adds an image entity that was read from the file via the creation interface.
1967  */
addImage(DL_CreationInterface * creationInterface)1968 void DL_Dxf::addImage(DL_CreationInterface* creationInterface) {
1969     DL_ImageData id(// pass ref insead of name we don't have yet
1970         values[340],
1971         // ins point:
1972         toReal(values[10], 0.0),
1973         toReal(values[20], 0.0),
1974         toReal(values[30], 0.0),
1975         // u vector:
1976         toReal(values[11], 1.0),
1977         toReal(values[21], 0.0),
1978         toReal(values[31], 0.0),
1979         // v vector:
1980         toReal(values[12], 0.0),
1981         toReal(values[22], 1.0),
1982         toReal(values[32], 0.0),
1983         // image size (pixel):
1984         toInt(values[13], 1),
1985         toInt(values[23], 1),
1986         // brightness, contrast, fade
1987         toInt(values[281], 50),
1988         toInt(values[282], 50),
1989         toInt(values[283], 0));
1990 
1991     creationInterface->addImage(id);
1992     creationInterface->endEntity();
1993     currentEntity = DL_UNKNOWN;
1994 }
1995 
1996 
1997 
1998 /**
1999  * Adds an image definition that was read from the file via the creation interface.
2000  */
addImageDef(DL_CreationInterface * creationInterface)2001 void DL_Dxf::addImageDef(DL_CreationInterface* creationInterface) {
2002     DL_ImageDefData id(// handle
2003         values[5],
2004         values[1]);
2005 
2006     creationInterface->linkImage(id);
2007     creationInterface->endEntity();
2008     currentEntity = DL_UNKNOWN;
2009 }
2010 
2011 
2012 
2013 /**
2014  * Ends some special entities like hatches or old style polylines.
2015  */
endEntity(DL_CreationInterface * creationInterface)2016 void DL_Dxf::endEntity(DL_CreationInterface* creationInterface) {
2017 	creationInterface->endEntity();
2018 }
2019 
2020 
2021 /**
2022  * Ends a sequence and notifies the creation interface.
2023  */
endSequence(DL_CreationInterface * creationInterface)2024 void DL_Dxf::endSequence(DL_CreationInterface* creationInterface) {
2025     creationInterface->endSequence();
2026 }
2027 
2028 
2029 /**
2030  * Converts the given string into an int.
2031  * ok is set to false if there was an error.
2032  */
stringToInt(const char * s,bool * ok)2033 int DL_Dxf::stringToInt(const char* s, bool* ok) {
2034     if (ok!=NULL) {
2035         // check string:
2036         *ok = true;
2037         int i=0;
2038         bool dot = false;
2039         do {
2040             if (s[i]=='\0') {
2041                 break;
2042             } else if (s[i]=='.') {
2043                 if (dot==true) {
2044                     //std::cerr << "two dots\n";
2045                     *ok = false;
2046                 } else {
2047                     dot = true;
2048                 }
2049             } else if (s[i]<'0' || s[i]>'9') {
2050                 //std::cerr << "NaN: '" << s[i] << "'\n";
2051                 *ok = false;
2052             }
2053             i++;
2054         } while(s[i]!='\0' && *ok==true);
2055     }
2056 
2057     return atoi(s);
2058 }
2059 
2060 
2061 /**
2062  * @brief Opens the given file for writing and returns a pointer
2063  * to the dxf writer. This pointer needs to be passed on to other
2064  * writing functions.
2065  *
2066  * @param file Full path of the file to open.
2067  *
2068  * @return Pointer to an ascii dxf writer object.
2069  */
out(const char * file,DL_Codes::version version)2070 DL_WriterA* DL_Dxf::out(const char* file, DL_Codes::version version) {
2071     char* f = new char[strlen(file)+1];
2072     strcpy(f, file);
2073     this->version = version;
2074 
2075     DL_WriterA* dw = new DL_WriterA(f, version);
2076     if (dw->openFailed()) {
2077         delete dw;
2078         delete[] f;
2079         return NULL;
2080     } else {
2081         delete[] f;
2082         return dw;
2083     }
2084 }
2085 
2086 
2087 
2088 /**
2089  * @brief Writes a DXF header to the file currently opened
2090  * by the given DXF writer object.
2091  */
writeHeader(DL_WriterA & dw)2092 void DL_Dxf::writeHeader(DL_WriterA& dw) {
2093     dw.comment("dxflib " DL_VERSION);
2094     dw.sectionHeader();
2095 
2096     dw.dxfString(9, "$ACADVER");
2097     switch (version) {
2098     case DL_Codes::AC1009:
2099         dw.dxfString(1, "AC1009");
2100         break;
2101     case DL_Codes::AC1012:
2102         dw.dxfString(1, "AC1012");
2103         break;
2104     case DL_Codes::AC1014:
2105         dw.dxfString(1, "AC1014");
2106         break;
2107     case DL_Codes::AC1015:
2108         dw.dxfString(1, "AC1015");
2109         break;
2110     }
2111 
2112     // Newer version require that (otherwise a*cad crashes..)
2113     if (version==VER_2000) {
2114         dw.dxfString(9, "$HANDSEED");
2115         dw.dxfHex(5, 0xFFFF);
2116     }
2117 
2118     //dw.sectionEnd();
2119 }
2120 
2121 
2122 
2123 
2124 /**
2125  * Writes a point entity to the file.
2126  *
2127  * @param dw DXF writer
2128  * @param data Entity data from the file
2129  * @param attrib Attributes
2130  */
writePoint(DL_WriterA & dw,const DL_PointData & data,const DL_Attributes & attrib)2131 void DL_Dxf::writePoint(DL_WriterA& dw,
2132                         const DL_PointData& data,
2133                         const DL_Attributes& attrib) {
2134     dw.entity("POINT");
2135     if (version==VER_2000) {
2136         dw.dxfString(100, "AcDbEntity");
2137         dw.dxfString(100, "AcDbPoint");
2138     }
2139     dw.entityAttributes(attrib);
2140     dw.coord(POINT_COORD_CODE, data.x, data.y);
2141 }
2142 
2143 
2144 
2145 /**
2146  * Writes a line entity to the file.
2147  *
2148  * @param dw DXF writer
2149  * @param data Entity data from the file
2150  * @param attrib Attributes
2151  */
writeLine(DL_WriterA & dw,const DL_LineData & data,const DL_Attributes & attrib)2152 void DL_Dxf::writeLine(DL_WriterA& dw,
2153                        const DL_LineData& data,
2154                        const DL_Attributes& attrib) {
2155     dw.entity("LINE");
2156     if (version==VER_2000) {
2157         dw.dxfString(100, "AcDbEntity");
2158         dw.dxfString(100, "AcDbLine");
2159     }
2160     dw.entityAttributes(attrib);
2161     dw.coord(LINE_START_CODE, data.x1, data.y1);
2162     dw.coord(LINE_END_CODE, data.x2, data.y2);
2163 }
2164 
2165 
2166 
2167 /**
2168  * Writes a polyline entity to the file.
2169  *
2170  * @param dw DXF writer
2171  * @param data Entity data from the file
2172  * @param attrib Attributes
2173  * @see writeVertex
2174  */
writePolyline(DL_WriterA & dw,const DL_PolylineData & data,const DL_Attributes & attrib)2175 void DL_Dxf::writePolyline(DL_WriterA& dw,
2176                            const DL_PolylineData& data,
2177                            const DL_Attributes& attrib) {
2178     if (version==VER_2000) {
2179         dw.entity("LWPOLYLINE");
2180         dw.entityAttributes(attrib);
2181         dw.dxfString(100, "AcDbEntity");
2182         dw.dxfString(100, "AcDbPolyline");
2183         dw.dxfInt(90, (int)data.number);
2184         dw.dxfInt(70, data.flags);
2185     } else {
2186         dw.entity("POLYLINE");
2187         dw.entityAttributes(attrib);
2188 		polylineLayer = attrib.getLayer();
2189         dw.dxfInt(66, 1);
2190         dw.dxfInt(70, data.flags);
2191         dw.coord(VERTEX_COORD_CODE, 0.0, 0.0);
2192     }
2193 }
2194 
2195 
2196 
2197 /**
2198  * Writes a single vertex of a polyline to the file.
2199  *
2200  * @param dw DXF writer
2201  * @param data Entity data from the file
2202  * @param attrib Attributes
2203  */
writeVertex(DL_WriterA & dw,const DL_VertexData & data)2204 void DL_Dxf::writeVertex(DL_WriterA& dw,
2205                          const DL_VertexData& data) {
2206 
2207 
2208     if (version==VER_2000) {
2209         dw.dxfReal(10, data.x);
2210         dw.dxfReal(20, data.y);
2211         if (fabs(data.bulge)>1.0e-10) {
2212             dw.dxfReal(42, data.bulge);
2213         }
2214     } else {
2215         dw.entity("VERTEX");
2216         //dw.entityAttributes(attrib);
2217     	dw.dxfString(8, polylineLayer);
2218         dw.coord(VERTEX_COORD_CODE, data.x, data.y);
2219         if (fabs(data.bulge)>1.0e-10) {
2220             dw.dxfReal(42, data.bulge);
2221         }
2222     }
2223 }
2224 
2225 
2226 
2227 /**
2228  * Writes the polyline end. Only needed for DXF R12.
2229  */
writePolylineEnd(DL_WriterA & dw)2230 void DL_Dxf::writePolylineEnd(DL_WriterA& dw) {
2231     if (version==VER_2000) {
2232     } else {
2233         dw.entity("SEQEND");
2234     }
2235 }
2236 
2237 
2238 /**
2239  * Writes a spline entity to the file.
2240  *
2241  * @param dw DXF writer
2242  * @param data Entity data from the file
2243  * @param attrib Attributes
2244  * @see writeControlPoint
2245  */
writeSpline(DL_WriterA & dw,const DL_SplineData & data,const DL_Attributes & attrib)2246 void DL_Dxf::writeSpline(DL_WriterA& dw,
2247                          const DL_SplineData& data,
2248                          const DL_Attributes& attrib) {
2249 
2250     dw.entity("SPLINE");
2251     dw.entityAttributes(attrib);
2252     if (version==VER_2000) {
2253         dw.dxfString(100, "AcDbEntity");
2254         dw.dxfString(100, "AcDbSpline");
2255     }
2256     dw.dxfInt(70, data.flags);
2257     dw.dxfInt(71, data.degree);
2258     dw.dxfInt(72, data.nKnots);            // number of knots
2259     dw.dxfInt(73, data.nControl);          // number of control points
2260     dw.dxfInt(74, 0);                      // number of fit points
2261 }
2262 
2263 
2264 
2265 /**
2266  * Writes a single control point of a spline to the file.
2267  *
2268  * @param dw DXF writer
2269  * @param data Entity data from the file
2270  * @param attrib Attributes
2271  */
writeControlPoint(DL_WriterA & dw,const DL_ControlPointData & data)2272 void DL_Dxf::writeControlPoint(DL_WriterA& dw,
2273                                const DL_ControlPointData& data) {
2274 
2275     dw.dxfReal(10, data.x);
2276     dw.dxfReal(20, data.y);
2277     dw.dxfReal(30, data.z);
2278 }
2279 
2280 
2281 
2282 /**
2283  * Writes a single knot of a spline to the file.
2284  *
2285  * @param dw DXF writer
2286  * @param data Entity data from the file
2287  * @param attrib Attributes
2288  */
writeKnot(DL_WriterA & dw,const DL_KnotData & data)2289 void DL_Dxf::writeKnot(DL_WriterA& dw,
2290                        const DL_KnotData& data) {
2291 
2292     dw.dxfReal(40, data.k);
2293 }
2294 
2295 
2296 
2297 /**
2298  * Writes a circle entity to the file.
2299  *
2300  * @param dw DXF writer
2301  * @param data Entity data from the file
2302  * @param attrib Attributes
2303  */
writeCircle(DL_WriterA & dw,const DL_CircleData & data,const DL_Attributes & attrib)2304 void DL_Dxf::writeCircle(DL_WriterA& dw,
2305                          const DL_CircleData& data,
2306                          const DL_Attributes& attrib) {
2307     dw.entity("CIRCLE");
2308     if (version==VER_2000) {
2309         dw.dxfString(100, "AcDbEntity");
2310         dw.dxfString(100, "AcDbCircle");
2311     }
2312     dw.entityAttributes(attrib);
2313     dw.coord(10, data.cx, data.cy);
2314     dw.dxfReal(40, data.radius);
2315 }
2316 
2317 
2318 
2319 /**
2320  * Writes an arc entity to the file.
2321  *
2322  * @param dw DXF writer
2323  * @param data Entity data from the file
2324  * @param attrib Attributes
2325  */
writeArc(DL_WriterA & dw,const DL_ArcData & data,const DL_Attributes & attrib)2326 void DL_Dxf::writeArc(DL_WriterA& dw,
2327                       const DL_ArcData& data,
2328                       const DL_Attributes& attrib) {
2329     dw.entity("ARC");
2330     if (version==VER_2000) {
2331         dw.dxfString(100, "AcDbEntity");
2332     }
2333     dw.entityAttributes(attrib);
2334     if (version==VER_2000) {
2335         dw.dxfString(100, "AcDbCircle");
2336     }
2337     dw.coord(10, data.cx, data.cy);
2338     dw.dxfReal(40, data.radius);
2339     if (version==VER_2000) {
2340         dw.dxfString(100, "AcDbArc");
2341     }
2342     dw.dxfReal(50, data.angle1);
2343     dw.dxfReal(51, data.angle2);
2344 }
2345 
2346 
2347 
2348 /**
2349  * Writes an ellipse entity to the file.
2350  *
2351  * @param dw DXF writer
2352  * @param data Entity data from the file
2353  * @param attrib Attributes
2354  */
writeEllipse(DL_WriterA & dw,const DL_EllipseData & data,const DL_Attributes & attrib)2355 void DL_Dxf::writeEllipse(DL_WriterA& dw,
2356                           const DL_EllipseData& data,
2357                           const DL_Attributes& attrib) {
2358 
2359     if (version>VER_R12) {
2360         dw.entity("ELLIPSE");
2361         if (version==VER_2000) {
2362             dw.dxfString(100, "AcDbEntity");
2363             dw.dxfString(100, "AcDbEllipse");
2364         }
2365         dw.entityAttributes(attrib);
2366         dw.coord(10, data.cx, data.cy);
2367         dw.coord(11, data.mx, data.my);
2368         dw.dxfReal(40, data.ratio);
2369         dw.dxfReal(41, data.angle1);
2370         dw.dxfReal(42, data.angle2);
2371     }
2372 }
2373 
2374 
2375 
2376 /**
2377  * Writes a solid entity to the file.
2378  *
2379  * @param dw DXF writer
2380  * @param data Entity data from the file
2381  * @param attrib Attributes
2382  */
writeSolid(DL_WriterA & dw,const DL_SolidData & data,const DL_Attributes & attrib)2383 void DL_Dxf::writeSolid(DL_WriterA& dw,
2384                    const DL_SolidData& data,
2385                    const DL_Attributes& attrib) {
2386     dw.entity("SOLID");
2387     if (version==VER_2000) {
2388         dw.dxfString(100, "AcDbEntity");
2389         dw.dxfString(100, "AcDbTrace");
2390     }
2391     dw.entityAttributes(attrib);
2392     dw.coord(10, data.x[0], data.y[0], data.z[0]);
2393     dw.coord(11, data.x[1], data.y[1], data.z[1]);
2394     dw.coord(12, data.x[2], data.y[2], data.z[2]);
2395     dw.coord(13, data.x[3], data.y[3], data.z[3]);
2396     dw.dxfReal(39, data.thickness);
2397 }
2398 
2399 
2400 
2401 /**
2402  * Writes a 3d face entity to the file.
2403  *
2404  * @param dw DXF writer
2405  * @param data Entity data from the file
2406  * @param attrib Attributes
2407  */
write3dFace(DL_WriterA & dw,const DL_3dFaceData & data,const DL_Attributes & attrib)2408 void DL_Dxf::write3dFace(DL_WriterA& dw,
2409                    const DL_3dFaceData& data,
2410                    const DL_Attributes& attrib) {
2411     dw.entity("3DFACE");
2412     if (version==VER_2000) {
2413         dw.dxfString(100, "AcDbEntity");
2414         dw.dxfString(100, "AcDbFace");
2415     }
2416     dw.entityAttributes(attrib);
2417     dw.coord(10, data.x[0], data.y[0], data.z[0]);
2418     dw.coord(11, data.x[1], data.y[1], data.z[1]);
2419     dw.coord(12, data.x[2], data.y[2], data.z[2]);
2420     dw.coord(13, data.x[3], data.y[3], data.z[3]);
2421 }
2422 
2423 
2424 
2425 /**
2426  * Writes an insert to the file.
2427  *
2428  * @param dw DXF writer
2429  * @param data Entity data from the file
2430  * @param attrib Attributes
2431  */
writeInsert(DL_WriterA & dw,const DL_InsertData & data,const DL_Attributes & attrib)2432 void DL_Dxf::writeInsert(DL_WriterA& dw,
2433                          const DL_InsertData& data,
2434                          const DL_Attributes& attrib) {
2435 
2436     if (data.name.empty()) {
2437         std::cerr << "DL_Dxf::writeInsert: "
2438         << "Block name must not be empty\n";
2439         return;
2440     }
2441 
2442     dw.entity("INSERT");
2443     if (version==VER_2000) {
2444         dw.dxfString(100, "AcDbEntity");
2445         dw.dxfString(100, "AcDbBlockReference");
2446     }
2447     dw.entityAttributes(attrib);
2448     dw.dxfString(2, data.name);
2449     dw.dxfReal(10, data.ipx);
2450     dw.dxfReal(20, data.ipy);
2451     dw.dxfReal(30, 0.0);
2452     if (data.sx!=1.0 || data.sy!=1.0) {
2453         dw.dxfReal(41, data.sx);
2454         dw.dxfReal(42, data.sy);
2455         dw.dxfReal(43, 1.0);
2456     }
2457     if (data.angle!=0.0) {
2458         dw.dxfReal(50, data.angle);
2459     }
2460     if (data.cols!=1 || data.rows!=1) {
2461         dw.dxfInt(70, data.cols);
2462         dw.dxfInt(71, data.rows);
2463     }
2464     if (data.colSp!=0.0 || data.rowSp!=0.0) {
2465         dw.dxfReal(44, data.colSp);
2466         dw.dxfReal(45, data.rowSp);
2467     }
2468 
2469 }
2470 
2471 
2472 
2473 /**
2474  * Writes a multi text entity to the file.
2475  *
2476  * @param dw DXF writer
2477  * @param data Entity data from the file
2478  * @param attrib Attributes
2479  */
writeMText(DL_WriterA & dw,const DL_MTextData & data,const DL_Attributes & attrib)2480 void DL_Dxf::writeMText(DL_WriterA& dw,
2481                         const DL_MTextData& data,
2482                         const DL_Attributes& attrib) {
2483 
2484     dw.entity("MTEXT");
2485     if (version==VER_2000) {
2486         dw.dxfString(100, "AcDbEntity");
2487         dw.dxfString(100, "AcDbMText");
2488     }
2489     dw.entityAttributes(attrib);
2490     dw.dxfReal(10, data.ipx);
2491     dw.dxfReal(20, data.ipy);
2492     dw.dxfReal(30, 0.0);
2493     dw.dxfReal(40, data.height);
2494     dw.dxfReal(41, data.width);
2495 
2496     dw.dxfInt(71, data.attachmentPoint);
2497     dw.dxfInt(72, data.drawingDirection);
2498 
2499     // Creare text chunks of 250 characters each:
2500     int length = data.text.length();
2501     char chunk[251];
2502     int i;
2503     for (i=250; i<length; i+=250) {
2504         strncpy(chunk, &data.text.c_str()[i-250], 250);
2505         chunk[250]='\0';
2506         dw.dxfString(3, chunk);
2507     }
2508     strncpy(chunk, &data.text.c_str()[i-250], 250);
2509     chunk[250]='\0';
2510     dw.dxfString(1, chunk);
2511 
2512     dw.dxfString(7, data.style);
2513 
2514     // since dxflib 2.0.2.1: degrees not rad (error in autodesk dxf doc)
2515     dw.dxfReal(50, data.angle/(2.0*M_PI)*360.0);
2516 
2517     dw.dxfInt(73, data.lineSpacingStyle);
2518     dw.dxfReal(44, data.lineSpacingFactor);
2519 }
2520 
2521 
2522 
2523 /**
2524  * Writes a text entity to the file.
2525  *
2526  * @param dw DXF writer
2527  * @param data Entity data from the file
2528  * @param attrib Attributes
2529  */
writeText(DL_WriterA & dw,const DL_TextData & data,const DL_Attributes & attrib)2530 void DL_Dxf::writeText(DL_WriterA& dw,
2531                        const DL_TextData& data,
2532                        const DL_Attributes& attrib) {
2533 
2534     dw.entity("TEXT");
2535     if (version==VER_2000) {
2536         dw.dxfString(100, "AcDbEntity");
2537         dw.dxfString(100, "AcDbText");
2538     }
2539     dw.entityAttributes(attrib);
2540     dw.dxfReal(10, data.ipx);
2541     dw.dxfReal(20, data.ipy);
2542     dw.dxfReal(30, 0.0);
2543     dw.dxfReal(40, data.height);
2544     dw.dxfString(1, data.text);
2545     dw.dxfReal(50, data.angle/(2*M_PI)*360.0);
2546     dw.dxfReal(41, data.xScaleFactor);
2547     dw.dxfString(7, data.style);
2548 
2549     dw.dxfInt(71, data.textGenerationFlags);
2550     dw.dxfInt(72, data.hJustification);
2551 
2552     dw.dxfReal(11, data.apx);
2553     dw.dxfReal(21, data.apy);
2554     dw.dxfReal(31, 0.0);
2555 
2556     dw.dxfInt(73, data.vJustification);
2557 }
2558 
2559 
2560 /**
2561  * Writes an aligned dimension entity to the file.
2562  *
2563  * @param dw DXF writer
2564  * @param data Generic dimension data for from the file
2565  * @param data Specific aligned dimension data from the file
2566  * @param attrib Attributes
2567  */
writeDimAligned(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimAlignedData & edata,const DL_Attributes & attrib)2568 void DL_Dxf::writeDimAligned(DL_WriterA& dw,
2569                              const DL_DimensionData& data,
2570                              const DL_DimAlignedData& edata,
2571                              const DL_Attributes& attrib) {
2572 
2573     dw.entity("DIMENSION");
2574 
2575     if (version==VER_2000) {
2576         dw.dxfString(100, "AcDbEntity");
2577     }
2578     dw.entityAttributes(attrib);
2579     if (version==VER_2000) {
2580         dw.dxfString(100, "AcDbDimension");
2581     }
2582 
2583     dw.dxfReal(10, data.dpx);
2584     dw.dxfReal(20, data.dpy);
2585     dw.dxfReal(30, 0.0);
2586 
2587     dw.dxfReal(11, data.mpx);
2588     dw.dxfReal(21, data.mpy);
2589     dw.dxfReal(31, 0.0);
2590 
2591     dw.dxfInt(70, 1);
2592     if (version>VER_R12) {
2593         dw.dxfInt(71, data.attachmentPoint);
2594         dw.dxfInt(72, data.lineSpacingStyle); // opt
2595         dw.dxfReal(41, data.lineSpacingFactor); // opt
2596     }
2597 
2598     dw.dxfReal(42, data.angle);
2599 
2600     dw.dxfString(1, data.text);   // opt
2601     //dw.dxfString(3, data.style);
2602     dw.dxfString(3, "Standard");
2603 
2604     if (version==VER_2000) {
2605         dw.dxfString(100, "AcDbAlignedDimension");
2606     }
2607 
2608     dw.dxfReal(13, edata.epx1);
2609     dw.dxfReal(23, edata.epy1);
2610     dw.dxfReal(33, 0.0);
2611 
2612     dw.dxfReal(14, edata.epx2);
2613     dw.dxfReal(24, edata.epy2);
2614     dw.dxfReal(34, 0.0);
2615 }
2616 
2617 
2618 
2619 /**
2620  * Writes a linear dimension entity to the file.
2621  *
2622  * @param dw DXF writer
2623  * @param data Generic dimension data for from the file
2624  * @param data Specific linear dimension data from the file
2625  * @param attrib Attributes
2626  */
writeDimLinear(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimLinearData & edata,const DL_Attributes & attrib)2627 void DL_Dxf::writeDimLinear(DL_WriterA& dw,
2628                             const DL_DimensionData& data,
2629                             const DL_DimLinearData& edata,
2630                             const DL_Attributes& attrib) {
2631 
2632     dw.entity("DIMENSION");
2633 
2634     if (version==VER_2000) {
2635         dw.dxfString(100, "AcDbEntity");
2636     }
2637     dw.entityAttributes(attrib);
2638     if (version==VER_2000) {
2639         dw.dxfString(100, "AcDbDimension");
2640     }
2641 
2642     dw.dxfReal(10, data.dpx);
2643     dw.dxfReal(20, data.dpy);
2644     dw.dxfReal(30, 0.0);
2645 
2646     dw.dxfReal(11, data.mpx);
2647     dw.dxfReal(21, data.mpy);
2648     dw.dxfReal(31, 0.0);
2649 
2650     dw.dxfInt(70, 0);
2651     if (version>VER_R12) {
2652         dw.dxfInt(71, data.attachmentPoint);
2653         dw.dxfInt(72, data.lineSpacingStyle); // opt
2654         dw.dxfReal(41, data.lineSpacingFactor); // opt
2655     }
2656 
2657     dw.dxfReal(42, data.angle);
2658 
2659     dw.dxfString(1, data.text);   // opt
2660     //dw.dxfString(3, data.style);
2661     dw.dxfString(3, "Standard");
2662 
2663     if (version==VER_2000) {
2664         dw.dxfString(100, "AcDbAlignedDimension");
2665     }
2666 
2667     dw.dxfReal(13, edata.dpx1);
2668     dw.dxfReal(23, edata.dpy1);
2669     dw.dxfReal(33, 0.0);
2670 
2671     dw.dxfReal(14, edata.dpx2);
2672     dw.dxfReal(24, edata.dpy2);
2673     dw.dxfReal(34, 0.0);
2674 
2675     dw.dxfReal(50, edata.angle/(2.0*M_PI)*360.0);
2676 
2677     if (version==VER_2000) {
2678         dw.dxfString(100, "AcDbRotatedDimension");
2679         /*
2680         dw.dxfString(1001, "ACAD");
2681         dw.dxfString(1000, "DSTYLE");
2682         dw.dxfString(1002, "{");
2683         dw.dxfInt(1070, 340);
2684         dw.dxfInt(1005, 11);
2685         dw.dxfString(1002, "}");
2686         */
2687     }
2688 }
2689 
2690 
2691 
2692 /**
2693  * Writes a radial dimension entity to the file.
2694  *
2695  * @param dw DXF writer
2696  * @param data Generic dimension data for from the file
2697  * @param data Specific radial dimension data from the file
2698  * @param attrib Attributes
2699  */
writeDimRadial(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimRadialData & edata,const DL_Attributes & attrib)2700 void DL_Dxf::writeDimRadial(DL_WriterA& dw,
2701                             const DL_DimensionData& data,
2702                             const DL_DimRadialData& edata,
2703                             const DL_Attributes& attrib) {
2704 
2705     dw.entity("DIMENSION");
2706 
2707     if (version==VER_2000) {
2708         dw.dxfString(100, "AcDbEntity");
2709     }
2710     dw.entityAttributes(attrib);
2711     if (version==VER_2000) {
2712         dw.dxfString(100, "AcDbDimension");
2713     }
2714 
2715     dw.dxfReal(10, data.dpx);
2716     dw.dxfReal(20, data.dpy);
2717     dw.dxfReal(30, 0.0);
2718 
2719     dw.dxfReal(11, data.mpx);
2720     dw.dxfReal(21, data.mpy);
2721     dw.dxfReal(31, 0.0);
2722 
2723     dw.dxfInt(70, 4);
2724     if (version>VER_R12) {
2725         dw.dxfInt(71, data.attachmentPoint);
2726         dw.dxfInt(72, data.lineSpacingStyle); // opt
2727         dw.dxfReal(41, data.lineSpacingFactor); // opt
2728     }
2729 
2730     dw.dxfReal(42, data.angle);
2731 
2732     dw.dxfString(1, data.text);   // opt
2733     //dw.dxfString(3, data.style);
2734     dw.dxfString(3, "Standard");
2735 
2736     if (version==VER_2000) {
2737         dw.dxfString(100, "AcDbRadialDimension");
2738     }
2739 
2740     dw.dxfReal(15, edata.dpx);
2741     dw.dxfReal(25, edata.dpy);
2742     dw.dxfReal(35, 0.0);
2743 
2744     dw.dxfReal(40, edata.leader);
2745 }
2746 
2747 
2748 
2749 /**
2750  * Writes a diametric dimension entity to the file.
2751  *
2752  * @param dw DXF writer
2753  * @param data Generic dimension data for from the file
2754  * @param data Specific diametric dimension data from the file
2755  * @param attrib Attributes
2756  */
writeDimDiametric(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimDiametricData & edata,const DL_Attributes & attrib)2757 void DL_Dxf::writeDimDiametric(DL_WriterA& dw,
2758                                const DL_DimensionData& data,
2759                                const DL_DimDiametricData& edata,
2760                                const DL_Attributes& attrib) {
2761 
2762     dw.entity("DIMENSION");
2763 
2764     if (version==VER_2000) {
2765         dw.dxfString(100, "AcDbEntity");
2766     }
2767     dw.entityAttributes(attrib);
2768     if (version==VER_2000) {
2769         dw.dxfString(100, "AcDbDimension");
2770     }
2771 
2772     dw.dxfReal(10, data.dpx);
2773     dw.dxfReal(20, data.dpy);
2774     dw.dxfReal(30, 0.0);
2775 
2776     dw.dxfReal(11, data.mpx);
2777     dw.dxfReal(21, data.mpy);
2778     dw.dxfReal(31, 0.0);
2779 
2780     dw.dxfInt(70, 3);
2781     if (version>VER_R12) {
2782         dw.dxfInt(71, data.attachmentPoint);
2783         dw.dxfInt(72, data.lineSpacingStyle); // opt
2784         dw.dxfReal(41, data.lineSpacingFactor); // opt
2785     }
2786 
2787     dw.dxfReal(42, data.angle);
2788 
2789     dw.dxfString(1, data.text);   // opt
2790     //dw.dxfString(3, data.style);
2791     dw.dxfString(3, "Standard");
2792 
2793     if (version==VER_2000) {
2794         dw.dxfString(100, "AcDbDiametricDimension");
2795     }
2796 
2797     dw.dxfReal(15, edata.dpx);
2798     dw.dxfReal(25, edata.dpy);
2799     dw.dxfReal(35, 0.0);
2800 
2801     dw.dxfReal(40, edata.leader);
2802 }
2803 
2804 
2805 
2806 /**
2807  * Writes an angular dimension entity to the file.
2808  *
2809  * @param dw DXF writer
2810  * @param data Generic dimension data for from the file
2811  * @param data Specific angular dimension data from the file
2812  * @param attrib Attributes
2813  */
writeDimAngular(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimAngularData & edata,const DL_Attributes & attrib)2814 void DL_Dxf::writeDimAngular(DL_WriterA& dw,
2815                              const DL_DimensionData& data,
2816                              const DL_DimAngularData& edata,
2817                              const DL_Attributes& attrib) {
2818 
2819     dw.entity("DIMENSION");
2820 
2821     if (version==VER_2000) {
2822         dw.dxfString(100, "AcDbEntity");
2823     }
2824     dw.entityAttributes(attrib);
2825     if (version==VER_2000) {
2826         dw.dxfString(100, "AcDbDimension");
2827     }
2828 
2829     dw.dxfReal(10, data.dpx);
2830     dw.dxfReal(20, data.dpy);
2831     dw.dxfReal(30, 0.0);
2832 
2833     dw.dxfReal(11, data.mpx);
2834     dw.dxfReal(21, data.mpy);
2835     dw.dxfReal(31, 0.0);
2836 
2837     dw.dxfInt(70, 2);
2838     if (version>VER_R12) {
2839         dw.dxfInt(71, data.attachmentPoint);
2840         dw.dxfInt(72, data.lineSpacingStyle); // opt
2841         dw.dxfReal(41, data.lineSpacingFactor); // opt
2842     }
2843 
2844     dw.dxfReal(42, data.angle);
2845 
2846     dw.dxfString(1, data.text);   // opt
2847     //dw.dxfString(3, data.style);
2848     dw.dxfString(3, "Standard");
2849 
2850     if (version==VER_2000) {
2851         dw.dxfString(100, "AcDb2LineAngularDimension");
2852     }
2853 
2854     dw.dxfReal(13, edata.dpx1);
2855     dw.dxfReal(23, edata.dpy1);
2856     dw.dxfReal(33, 0.0);
2857 
2858     dw.dxfReal(14, edata.dpx2);
2859     dw.dxfReal(24, edata.dpy2);
2860     dw.dxfReal(34, 0.0);
2861 
2862     dw.dxfReal(15, edata.dpx3);
2863     dw.dxfReal(25, edata.dpy3);
2864     dw.dxfReal(35, 0.0);
2865 
2866     dw.dxfReal(16, edata.dpx4);
2867     dw.dxfReal(26, edata.dpy4);
2868     dw.dxfReal(36, 0.0);
2869 }
2870 
2871 
2872 
2873 /**
2874  * Writes an angular dimension entity (3 points version) to the file.
2875  *
2876  * @param dw DXF writer
2877  * @param data Generic dimension data for from the file
2878  * @param data Specific angular dimension data from the file
2879  * @param attrib Attributes
2880  */
writeDimAngular3P(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimAngular3PData & edata,const DL_Attributes & attrib)2881 void DL_Dxf::writeDimAngular3P(DL_WriterA& dw,
2882                                const DL_DimensionData& data,
2883                                const DL_DimAngular3PData& edata,
2884                                const DL_Attributes& attrib) {
2885 
2886     dw.entity("DIMENSION");
2887 
2888     if (version==VER_2000) {
2889         dw.dxfString(100, "AcDbEntity");
2890     }
2891     dw.entityAttributes(attrib);
2892     if (version==VER_2000) {
2893         dw.dxfString(100, "AcDbDimension");
2894     }
2895 
2896     dw.dxfReal(10, data.dpx);
2897     dw.dxfReal(20, data.dpy);
2898     dw.dxfReal(30, 0.0);
2899 
2900     dw.dxfReal(11, data.mpx);
2901     dw.dxfReal(21, data.mpy);
2902     dw.dxfReal(31, 0.0);
2903 
2904     dw.dxfInt(70, 5);
2905     if (version>VER_R12) {
2906         dw.dxfInt(71, data.attachmentPoint);
2907         dw.dxfInt(72, data.lineSpacingStyle); // opt
2908         dw.dxfReal(41, data.lineSpacingFactor); // opt
2909     }
2910 
2911     dw.dxfReal(42, data.angle);
2912 
2913     dw.dxfString(1, data.text);   // opt
2914     //dw.dxfString(3, data.style);
2915     dw.dxfString(3, "Standard");
2916 
2917     if (version==VER_2000) {
2918         dw.dxfString(100, "AcDb3PointAngularDimension");
2919     }
2920 
2921     dw.dxfReal(13, edata.dpx1);
2922     dw.dxfReal(23, edata.dpy1);
2923     dw.dxfReal(33, 0.0);
2924 
2925     dw.dxfReal(14, edata.dpx2);
2926     dw.dxfReal(24, edata.dpy2);
2927     dw.dxfReal(34, 0.0);
2928 
2929     dw.dxfReal(15, edata.dpx3);
2930     dw.dxfReal(25, edata.dpy3);
2931     dw.dxfReal(35, 0.0);
2932 }
2933 
2934 
2935 
2936 
2937 /**
2938  * Writes an ordinate dimension entity to the file.
2939  *
2940  * @param dw DXF writer
2941  * @param data Generic dimension data for from the file
2942  * @param data Specific ordinate dimension data from the file
2943  * @param attrib Attributes
2944  */
writeDimOrdinate(DL_WriterA & dw,const DL_DimensionData & data,const DL_DimOrdinateData & edata,const DL_Attributes & attrib)2945 void DL_Dxf::writeDimOrdinate(DL_WriterA& dw,
2946                              const DL_DimensionData& data,
2947                              const DL_DimOrdinateData& edata,
2948                              const DL_Attributes& attrib) {
2949 
2950     dw.entity("DIMENSION");
2951 
2952     if (version==VER_2000) {
2953         dw.dxfString(100, "AcDbEntity");
2954     }
2955     dw.entityAttributes(attrib);
2956     if (version==VER_2000) {
2957         dw.dxfString(100, "AcDbDimension");
2958     }
2959 
2960     dw.dxfReal(10, data.dpx);
2961     dw.dxfReal(20, data.dpy);
2962     dw.dxfReal(30, 0.0);
2963 
2964     dw.dxfReal(11, data.mpx);
2965     dw.dxfReal(21, data.mpy);
2966     dw.dxfReal(31, 0.0);
2967 
2968     int type = 6;
2969     if (edata.xtype) {
2970         type+=64;
2971     }
2972 
2973     dw.dxfInt(70, type);
2974     if (version>VER_R12) {
2975         dw.dxfInt(71, data.attachmentPoint);
2976         dw.dxfInt(72, data.lineSpacingStyle); // opt
2977         dw.dxfReal(41, data.lineSpacingFactor); // opt
2978     }
2979 
2980     dw.dxfString(1, data.text);   // opt
2981     //dw.dxfString(3, data.style);
2982     dw.dxfString(3, "Standard");
2983 
2984     if (version==VER_2000) {
2985         dw.dxfString(100, "AcDbOrdinateDimension");
2986     }
2987 
2988     dw.dxfReal(13, edata.dpx1);
2989     dw.dxfReal(23, edata.dpy1);
2990     dw.dxfReal(33, 0.0);
2991 
2992     dw.dxfReal(14, edata.dpx2);
2993     dw.dxfReal(24, edata.dpy2);
2994     dw.dxfReal(34, 0.0);
2995 }
2996 
2997 
2998 
2999 /**
3000  * Writes a leader entity to the file.
3001  *
3002  * @param dw DXF writer
3003  * @param data Entity data from the file
3004  * @param attrib Attributes
3005  * @see writeVertex
3006  */
writeLeader(DL_WriterA & dw,const DL_LeaderData & data,const DL_Attributes & attrib)3007 void DL_Dxf::writeLeader(DL_WriterA& dw,
3008                          const DL_LeaderData& data,
3009                          const DL_Attributes& attrib) {
3010     if (version>VER_R12) {
3011         dw.entity("LEADER");
3012         dw.entityAttributes(attrib);
3013         if (version==VER_2000) {
3014             dw.dxfString(100, "AcDbEntity");
3015             dw.dxfString(100, "AcDbLeader");
3016         }
3017         dw.dxfString(3, "Standard");
3018         dw.dxfInt(71, data.arrowHeadFlag);
3019         dw.dxfInt(72, data.leaderPathType);
3020         dw.dxfInt(73, data.leaderCreationFlag);
3021         dw.dxfInt(74, data.hooklineDirectionFlag);
3022         dw.dxfInt(75, data.hooklineFlag);
3023         dw.dxfReal(40, data.textAnnotationHeight);
3024         dw.dxfReal(41, data.textAnnotationWidth);
3025         dw.dxfInt(76, data.number);
3026     }
3027 }
3028 
3029 
3030 
3031 /**
3032  * Writes a single vertex of a leader to the file.
3033  *
3034  * @param dw DXF writer
3035  * @param data Entity data
3036  */
writeLeaderVertex(DL_WriterA & dw,const DL_LeaderVertexData & data)3037 void DL_Dxf::writeLeaderVertex(DL_WriterA& dw,
3038                                const DL_LeaderVertexData& data) {
3039     if (version>VER_R12) {
3040         dw.dxfReal(10, data.x);
3041         dw.dxfReal(20, data.y);
3042     }
3043 }
3044 
3045 
3046 
3047 /**
3048  * Writes the beginning of a hatch entity to the file.
3049  * This must be followed by one or more writeHatchLoop()
3050  * calls and a writeHatch2() call.
3051  *
3052  * @param dw DXF writer
3053  * @param data Entity data.
3054  * @param attrib Attributes
3055  */
writeHatch1(DL_WriterA & dw,const DL_HatchData & data,const DL_Attributes & attrib)3056 void DL_Dxf::writeHatch1(DL_WriterA& dw,
3057                          const DL_HatchData& data,
3058                          const DL_Attributes& attrib) {
3059 
3060     dw.entity("HATCH");
3061     dw.entityAttributes(attrib);
3062     if (version==VER_2000) {
3063         dw.dxfString(100, "AcDbEntity");
3064         dw.dxfString(100, "AcDbHatch");
3065     }
3066     dw.dxfReal(10, 0.0);             // elevation
3067     dw.dxfReal(20, 0.0);
3068     dw.dxfReal(30, 0.0);
3069     dw.dxfReal(210, 0.0);             // extrusion dir.
3070     dw.dxfReal(220, 0.0);
3071     dw.dxfReal(230, 1.0);
3072     if (data.solid==false) {
3073         dw.dxfString(2, data.pattern);
3074     } else {
3075         dw.dxfString(2, "SOLID");
3076     }
3077     dw.dxfInt(70, (int)data.solid);
3078     dw.dxfInt(71, 0);                // associative
3079     dw.dxfInt(91, data.numLoops);
3080 }
3081 
3082 
3083 
3084 /**
3085  * Writes the end of a hatch entity to the file.
3086  *
3087  * @param dw DXF writer
3088  * @param data Entity data.
3089  * @param attrib Attributes
3090  */
writeHatch2(DL_WriterA & dw,const DL_HatchData & data,const DL_Attributes &)3091 void DL_Dxf::writeHatch2(DL_WriterA& dw,
3092                          const DL_HatchData& data,
3093                          const DL_Attributes& /*attrib*/) {
3094 
3095     dw.dxfInt(75, 0);                // odd parity
3096     dw.dxfInt(76, 1);                // pattern type
3097     if (data.solid==false) {
3098         dw.dxfReal(52, data.angle);
3099         dw.dxfReal(41, data.scale);
3100         dw.dxfInt(77, 0);            // not double
3101         //dw.dxfInt(78, 0);
3102         dw.dxfInt(78, 1);
3103         dw.dxfReal(53, 45.0);
3104         dw.dxfReal(43, 0.0);
3105         dw.dxfReal(44, 0.0);
3106         dw.dxfReal(45, -0.0883883476483184);
3107         dw.dxfReal(46, 0.0883883476483185);
3108         dw.dxfInt(79, 0);
3109     }
3110     dw.dxfInt(98, 0);
3111 }
3112 
3113 
3114 
3115 /**
3116  * Writes the beginning of a hatch loop to the file. This
3117  * must happen after writing the beginning of a hatch entity.
3118  *
3119  * @param dw DXF writer
3120  * @param data Entity data.
3121  * @param attrib Attributes
3122  */
writeHatchLoop1(DL_WriterA & dw,const DL_HatchLoopData & data)3123 void DL_Dxf::writeHatchLoop1(DL_WriterA& dw,
3124                              const DL_HatchLoopData& data) {
3125 
3126     dw.dxfInt(92, 1);
3127     dw.dxfInt(93, data.numEdges);
3128     //dw.dxfInt(97, 0);
3129 }
3130 
3131 
3132 
3133 /**
3134  * Writes the end of a hatch loop to the file.
3135  *
3136  * @param dw DXF writer
3137  * @param data Entity data.
3138  * @param attrib Attributes
3139  */
writeHatchLoop2(DL_WriterA & dw,const DL_HatchLoopData &)3140 void DL_Dxf::writeHatchLoop2(DL_WriterA& dw,
3141                              const DL_HatchLoopData& /*data*/) {
3142 
3143     dw.dxfInt(97, 0);
3144 }
3145 
3146 
3147 /**
3148  * Writes the beginning of a hatch entity to the file.
3149  *
3150  * @param dw DXF writer
3151  * @param data Entity data.
3152  * @param attrib Attributes
3153  */
writeHatchEdge(DL_WriterA & dw,const DL_HatchEdgeData & data)3154 void DL_Dxf::writeHatchEdge(DL_WriterA& dw,
3155                             const DL_HatchEdgeData& data) {
3156 
3157     dw.dxfInt(72, data.type);
3158 
3159     switch (data.type) {
3160     case 1:
3161         dw.dxfReal(10, data.x1);
3162         dw.dxfReal(20, data.y1);
3163         dw.dxfReal(11, data.x2);
3164         dw.dxfReal(21, data.y2);
3165         break;
3166     case 2:
3167         dw.dxfReal(10, data.cx);
3168         dw.dxfReal(20, data.cy);
3169         dw.dxfReal(40, data.radius);
3170         dw.dxfReal(50, data.angle1/(2*M_PI)*360.0);
3171         dw.dxfReal(51, data.angle2/(2*M_PI)*360.0);
3172         dw.dxfInt(73, (int)(data.ccw));
3173         break;
3174     default:
3175         break;
3176     }
3177 }
3178 
3179 
3180 
3181 /**
3182  * Writes an image entity.
3183  *
3184  * @return IMAGEDEF handle. Needed for the IMAGEDEF counterpart.
3185  */
writeImage(DL_WriterA & dw,const DL_ImageData & data,const DL_Attributes & attrib)3186 int DL_Dxf::writeImage(DL_WriterA& dw,
3187                        const DL_ImageData& data,
3188                        const DL_Attributes& attrib) {
3189 
3190     /*if (data.file.empty()) {
3191         std::cerr << "DL_Dxf::writeImage: "
3192         << "Image file must not be empty\n";
3193         return;
3194 }*/
3195 
3196     dw.entity("IMAGE");
3197 
3198     dw.entityAttributes(attrib);
3199     if (version==VER_2000) {
3200         dw.dxfString(100, "AcDbEntity");
3201         dw.dxfString(100, "AcDbRasterImage");
3202         dw.dxfInt(90, 0);
3203     }
3204     // insertion point
3205     dw.dxfReal(10, data.ipx);
3206     dw.dxfReal(20, data.ipy);
3207     dw.dxfReal(30, 0.0);
3208 
3209     // vector along bottom side (1 pixel long)
3210     dw.dxfReal(11, data.ux);
3211     dw.dxfReal(21, data.uy);
3212     dw.dxfReal(31, 0.0);
3213 
3214     // vector along left side (1 pixel long)
3215     dw.dxfReal(12, data.vx);
3216     dw.dxfReal(22, data.vy);
3217     dw.dxfReal(32, 0.0);
3218 
3219     // image size in pixel
3220     dw.dxfReal(13, data.width);
3221     dw.dxfReal(23, data.height);
3222 
3223     // handle of IMAGEDEF object
3224     int handle = dw.incHandle();
3225     dw.dxfHex(340, handle);
3226 
3227     // flags
3228     dw.dxfInt(70, 15);
3229 
3230     // clipping:
3231     dw.dxfInt(280, 0);
3232 
3233     // brightness, contrast, fade
3234     dw.dxfInt(281, data.brightness);
3235     dw.dxfInt(282, data.contrast);
3236     dw.dxfInt(283, data.fade);
3237 
3238     return handle;
3239 }
3240 
3241 
3242 
3243 /**
3244  * Writes an image definiition entity.
3245  */
writeImageDef(DL_WriterA & dw,int handle,const DL_ImageData & data)3246 void DL_Dxf::writeImageDef(DL_WriterA& dw,
3247                            int handle,
3248                            const DL_ImageData& data) {
3249 
3250     /*if (data.file.empty()) {
3251         std::cerr << "DL_Dxf::writeImage: "
3252         << "Image file must not be empty\n";
3253         return;
3254 }*/
3255 
3256     dw.dxfString(0, "IMAGEDEF");
3257     if (version==VER_2000) {
3258     	dw.dxfHex(5, handle);
3259 	}
3260 
3261     if (version==VER_2000) {
3262         dw.dxfString(100, "AcDbRasterImageDef");
3263         dw.dxfInt(90, 0);
3264     }
3265     // file name:
3266     dw.dxfString(1, data.ref);
3267 
3268     // image size in pixel
3269     dw.dxfReal(10, data.width);
3270     dw.dxfReal(20, data.height);
3271 
3272     dw.dxfReal(11, 1.0);
3273     dw.dxfReal(21, 1.0);
3274 
3275     // loaded:
3276     dw.dxfInt(280, 1);
3277     // units:
3278     dw.dxfInt(281, 0);
3279 }
3280 
3281 
3282 /**
3283  * Writes a layer to the file. Layers are stored in the
3284  * tables section of a DXF file.
3285  *
3286  * @param dw DXF writer
3287  * @param data Entity data from the file
3288  * @param attrib Attributes
3289  */
writeLayer(DL_WriterA & dw,const DL_LayerData & data,const DL_Attributes & attrib)3290 void DL_Dxf::writeLayer(DL_WriterA& dw,
3291                         const DL_LayerData& data,
3292                         const DL_Attributes& attrib) {
3293 
3294     if (data.name.empty()) {
3295         std::cerr << "DL_Dxf::writeLayer: "
3296         << "Layer name must not be empty\n";
3297         return;
3298     }
3299 
3300     int color = attrib.getColor();
3301     if (color>=256) {
3302         std::cerr << "Layer color cannot be " << color << ". Changed to 7.\n";
3303         color = 7;
3304     }
3305 
3306     if (data.name == "0") {
3307         dw.tableLayerEntry(0x10);
3308     } else {
3309         dw.tableLayerEntry();
3310     }
3311 
3312     dw.dxfString(2, data.name);
3313     dw.dxfInt(70, data.flags);
3314     dw.dxfInt(62, color);
3315 
3316     dw.dxfString(6, (attrib.getLineType().length()==0 ?
3317                      string("CONTINUOUS") : attrib.getLineType()));
3318 
3319     if (version>=VER_2000) {
3320         // layer defpoints cannot be plotted
3321         std::string lstr = data.name;
3322         std::transform(lstr.begin(), lstr.end(), lstr.begin(), tolower);
3323         if (lstr=="defpoints") {
3324             dw.dxfInt(290, 0);
3325         }
3326     }
3327     if (version>=VER_2000 && attrib.getWidth()!=-1) {
3328         dw.dxfInt(370, attrib.getWidth());
3329     }
3330     if (version>=VER_2000) {
3331         dw.dxfHex(390, 0xF);
3332     }
3333 }
3334 
3335 
3336 
3337 /**
3338  * Writes a line type to the file. Line types are stored in the
3339  * tables section of a DXF file.
3340  */
writeLineType(DL_WriterA & dw,const DL_LineTypeData & data)3341 void DL_Dxf::writeLineType(DL_WriterA& dw,
3342                            const DL_LineTypeData& data) {
3343     //const char* description,
3344     //int elements,
3345     //double patternLength) {
3346 
3347     if (data.name.empty()) {
3348         std::cerr << "DL_Dxf::writeLineType: "
3349         << "Line type name must not be empty\n";
3350         return;
3351     }
3352 
3353 	// ignore BYLAYER, BYBLOCK for R12
3354 	if (version<VER_2000) {
3355 		if (!strcasecmp(data.name.c_str(), "BYBLOCK") ||
3356 		    !strcasecmp(data.name.c_str(), "BYLAYER")) {
3357 			return;
3358 		}
3359 	}
3360 
3361 	// write id (not for R12)
3362     if (!strcasecmp(data.name.c_str(), "BYBLOCK")) {
3363         dw.tableLineTypeEntry(0x14);
3364     } else if (!strcasecmp(data.name.c_str(), "BYLAYER")) {
3365         dw.tableLineTypeEntry(0x15);
3366     } else if (!strcasecmp(data.name.c_str(), "CONTINUOUS")) {
3367         dw.tableLineTypeEntry(0x16);
3368     } else {
3369         dw.tableLineTypeEntry();
3370     }
3371 
3372     dw.dxfString(2, data.name);
3373 	//if (version>=VER_2000) {
3374     	dw.dxfInt(70, data.flags);
3375 	//}
3376 
3377     if (!strcasecmp(data.name.c_str(), "BYBLOCK")) {
3378         dw.dxfString(3, "");
3379         dw.dxfInt(72, 65);
3380         dw.dxfInt(73, 0);
3381         dw.dxfReal(40, 0.0);
3382     } else if (!strcasecmp(data.name.c_str(), "BYLAYER")) {
3383         dw.dxfString(3, "");
3384         dw.dxfInt(72, 65);
3385         dw.dxfInt(73, 0);
3386         dw.dxfReal(40, 0.0);
3387     } else if (!strcasecmp(data.name.c_str(), "CONTINUOUS")) {
3388         dw.dxfString(3, "Solid line");
3389         dw.dxfInt(72, 65);
3390         dw.dxfInt(73, 0);
3391         dw.dxfReal(40, 0.0);
3392     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO02W100")) {
3393         dw.dxfString(3, "ISO Dashed __ __ __ __ __ __ __ __ __ __ _");
3394         dw.dxfInt(72, 65);
3395         dw.dxfInt(73, 2);
3396         dw.dxfReal(40, 15.0);
3397         dw.dxfReal(49, 12.0);
3398         if (version>=VER_R13)
3399             dw.dxfInt(74, 0);
3400         dw.dxfReal(49, -3.0);
3401         if (version>=VER_R13)
3402             dw.dxfInt(74, 0);
3403     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO03W100")) {
3404         dw.dxfString(3, "ISO Dashed with Distance __    __    __    _");
3405         dw.dxfInt(72, 65);
3406         dw.dxfInt(73, 2);
3407         dw.dxfReal(40, 30.0);
3408         dw.dxfReal(49, 12.0);
3409         if (version>=VER_R13)
3410             dw.dxfInt(74, 0);
3411         dw.dxfReal(49, -18.0);
3412         if (version>=VER_R13)
3413             dw.dxfInt(74, 0);
3414     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO04W100")) {
3415         dw.dxfString(3, "ISO Long Dashed Dotted ____ . ____ . __");
3416         dw.dxfInt(72, 65);
3417         dw.dxfInt(73, 4);
3418         dw.dxfReal(40, 30.0);
3419         dw.dxfReal(49, 24.0);
3420         if (version>=VER_R13)
3421             dw.dxfInt(74, 0);
3422         dw.dxfReal(49, -3.0);
3423         if (version>=VER_R13)
3424             dw.dxfInt(74, 0);
3425         dw.dxfReal(49, 0.0);
3426         if (version>=VER_R13)
3427             dw.dxfInt(74, 0);
3428         dw.dxfReal(49, -3.0);
3429         if (version>=VER_R13)
3430             dw.dxfInt(74, 0);
3431     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO05W100")) {
3432         dw.dxfString(3, "ISO Long Dashed Double Dotted ____ .. __");
3433         dw.dxfInt(72, 65);
3434         dw.dxfInt(73, 6);
3435         dw.dxfReal(40, 33.0);
3436         dw.dxfReal(49, 24.0);
3437         if (version>=VER_R13)
3438             dw.dxfInt(74, 0);
3439         dw.dxfReal(49, -3.0);
3440         if (version>=VER_R13)
3441             dw.dxfInt(74, 0);
3442         dw.dxfReal(49, 0.0);
3443         if (version>=VER_R13)
3444             dw.dxfInt(74, 0);
3445         dw.dxfReal(49, -3.0);
3446         if (version>=VER_R13)
3447             dw.dxfInt(74, 0);
3448         dw.dxfReal(49, 0.0);
3449         if (version>=VER_R13)
3450             dw.dxfInt(74, 0);
3451         dw.dxfReal(49, -3.0);
3452         if (version>=VER_R13)
3453             dw.dxfInt(74, 0);
3454     } else if (!strcasecmp(data.name.c_str(), "BORDER")) {
3455         dw.dxfString(3, "Border __ __ . __ __ . __ __ . __ __ . __ __ .");
3456         dw.dxfInt(72, 65);
3457         dw.dxfInt(73, 6);
3458         dw.dxfReal(40, 44.45);
3459         dw.dxfReal(49, 12.7);
3460         if (version>=VER_R13)
3461             dw.dxfInt(74, 0);
3462         dw.dxfReal(49, -6.35);
3463         if (version>=VER_R13)
3464             dw.dxfInt(74, 0);
3465         dw.dxfReal(49, 12.7);
3466         if (version>=VER_R13)
3467             dw.dxfInt(74, 0);
3468         dw.dxfReal(49, -6.35);
3469         if (version>=VER_R13)
3470             dw.dxfInt(74, 0);
3471         dw.dxfReal(49, 0.0);
3472         if (version>=VER_R13)
3473             dw.dxfInt(74, 0);
3474         dw.dxfReal(49, -6.35);
3475         if (version>=VER_R13)
3476             dw.dxfInt(74, 0);
3477     } else if (!strcasecmp(data.name.c_str(), "BORDER2")) {
3478         dw.dxfString(3, "Border (.5x) __.__.__.__.__.__.__.__.__.__.__.");
3479         dw.dxfInt(72, 65);
3480         dw.dxfInt(73, 6);
3481         dw.dxfReal(40, 22.225);
3482         dw.dxfReal(49, 6.35);
3483         if (version>=VER_R13)
3484             dw.dxfInt(74, 0);
3485         dw.dxfReal(49, -3.175);
3486         if (version>=VER_R13)
3487             dw.dxfInt(74, 0);
3488         dw.dxfReal(49, 6.35);
3489         if (version>=VER_R13)
3490             dw.dxfInt(74, 0);
3491         dw.dxfReal(49, -3.175);
3492         if (version>=VER_R13)
3493             dw.dxfInt(74, 0);
3494         dw.dxfReal(49, 0.0);
3495         if (version>=VER_R13)
3496             dw.dxfInt(74, 0);
3497         dw.dxfReal(49, -3.175);
3498         if (version>=VER_R13)
3499             dw.dxfInt(74, 0);
3500     } else if (!strcasecmp(data.name.c_str(), "BORDERX2")) {
3501         dw.dxfString(3, "Border (2x) ____  ____  .  ____  ____  .  ___");
3502         dw.dxfInt(72, 65);
3503         dw.dxfInt(73, 6);
3504         dw.dxfReal(40, 88.9);
3505         dw.dxfReal(49, 25.4);
3506         if (version>=VER_R13)
3507             dw.dxfInt(74, 0);
3508         dw.dxfReal(49, -12.7);
3509         if (version>=VER_R13)
3510             dw.dxfInt(74, 0);
3511         dw.dxfReal(49, 25.4);
3512         if (version>=VER_R13)
3513             dw.dxfInt(74, 0);
3514         dw.dxfReal(49, -12.7);
3515         if (version>=VER_R13)
3516             dw.dxfInt(74, 0);
3517         dw.dxfReal(49, 0.0);
3518         if (version>=VER_R13)
3519             dw.dxfInt(74, 0);
3520         dw.dxfReal(49, -12.7);
3521         if (version>=VER_R13)
3522             dw.dxfInt(74, 0);
3523     } else if (!strcasecmp(data.name.c_str(), "CENTER")) {
3524         dw.dxfString(3, "Center ____ _ ____ _ ____ _ ____ _ ____ _ ____");
3525         dw.dxfInt(72, 65);
3526         dw.dxfInt(73, 4);
3527         dw.dxfReal(40, 50.8);
3528         dw.dxfReal(49, 31.75);
3529         if (version>=VER_R13)
3530             dw.dxfInt(74, 0);
3531         dw.dxfReal(49, -6.35);
3532         if (version>=VER_R13)
3533             dw.dxfInt(74, 0);
3534         dw.dxfReal(49, 6.35);
3535         if (version>=VER_R13)
3536             dw.dxfInt(74, 0);
3537         dw.dxfReal(49, -6.35);
3538         if (version>=VER_R13)
3539             dw.dxfInt(74, 0);
3540     } else if (!strcasecmp(data.name.c_str(), "CENTER2")) {
3541         dw.dxfString(3, "Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___");
3542         dw.dxfInt(72, 65);
3543         dw.dxfInt(73, 4);
3544         dw.dxfReal(40, 28.575);
3545         dw.dxfReal(49, 19.05);
3546         if (version>=VER_R13)
3547             dw.dxfInt(74, 0);
3548         dw.dxfReal(49, -3.175);
3549         if (version>=VER_R13)
3550             dw.dxfInt(74, 0);
3551         dw.dxfReal(49, 3.175);
3552         if (version>=VER_R13)
3553             dw.dxfInt(74, 0);
3554         dw.dxfReal(49, -3.175);
3555         if (version>=VER_R13)
3556             dw.dxfInt(74, 0);
3557     } else if (!strcasecmp(data.name.c_str(), "CENTERX2")) {
3558         dw.dxfString(3, "Center (2x) ________  __  ________  __  _____");
3559         dw.dxfInt(72, 65);
3560         dw.dxfInt(73, 4);
3561         dw.dxfReal(40, 101.6);
3562         dw.dxfReal(49, 63.5);
3563         if (version>=VER_R13)
3564             dw.dxfInt(74, 0);
3565         dw.dxfReal(49, -12.7);
3566         if (version>=VER_R13)
3567             dw.dxfInt(74, 0);
3568         dw.dxfReal(49, 12.7);
3569         if (version>=VER_R13)
3570             dw.dxfInt(74, 0);
3571         dw.dxfReal(49, -12.7);
3572         if (version>=VER_R13)
3573             dw.dxfInt(74, 0);
3574     } else if (!strcasecmp(data.name.c_str(), "DASHDOT")) {
3575         dw.dxfString(3, "Dash dot __ . __ . __ . __ . __ . __ . __ . __");
3576         dw.dxfInt(72, 65);
3577         dw.dxfInt(73, 4);
3578         dw.dxfReal(40, 25.4);
3579         dw.dxfReal(49, 12.7);
3580         if (version>=VER_R13)
3581             dw.dxfInt(74, 0);
3582         dw.dxfReal(49, -6.35);
3583         if (version>=VER_R13)
3584             dw.dxfInt(74, 0);
3585         dw.dxfReal(49, 0.0);
3586         if (version>=VER_R13)
3587             dw.dxfInt(74, 0);
3588         dw.dxfReal(49, -6.35);
3589         if (version>=VER_R13)
3590             dw.dxfInt(74, 0);
3591     } else if (!strcasecmp(data.name.c_str(), "DASHDOT2")) {
3592         dw.dxfString(3, "Dash dot (.5x) _._._._._._._._._._._._._._._.");
3593         dw.dxfInt(72, 65);
3594         dw.dxfInt(73, 4);
3595         dw.dxfReal(40, 12.7);
3596         dw.dxfReal(49, 6.35);
3597         if (version>=VER_R13)
3598             dw.dxfInt(74, 0);
3599         dw.dxfReal(49, -3.175);
3600         if (version>=VER_R13)
3601             dw.dxfInt(74, 0);
3602         dw.dxfReal(49, 0.0);
3603         if (version>=VER_R13)
3604             dw.dxfInt(74, 0);
3605         dw.dxfReal(49, -3.175);
3606         if (version>=VER_R13)
3607             dw.dxfInt(74, 0);
3608     } else if (!strcasecmp(data.name.c_str(), "DASHDOTX2")) {
3609         dw.dxfString(3, "Dash dot (2x) ____  .  ____  .  ____  .  ___");
3610         dw.dxfInt(72, 65);
3611         dw.dxfInt(73, 4);
3612         dw.dxfReal(40, 50.8);
3613         dw.dxfReal(49, 25.4);
3614         if (version>=VER_R13)
3615             dw.dxfInt(74, 0);
3616         dw.dxfReal(49, -12.7);
3617         if (version>=VER_R13)
3618             dw.dxfInt(74, 0);
3619         dw.dxfReal(49, 0.0);
3620         if (version>=VER_R13)
3621             dw.dxfInt(74, 0);
3622         dw.dxfReal(49, -12.7);
3623         if (version>=VER_R13)
3624             dw.dxfInt(74, 0);
3625     } else if (!strcasecmp(data.name.c_str(), "DASHED")) {
3626         dw.dxfString(3, "Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _");
3627         dw.dxfInt(72, 65);
3628         dw.dxfInt(73, 2);
3629         dw.dxfReal(40, 19.05);
3630         dw.dxfReal(49, 12.7);
3631         if (version>=VER_R13)
3632             dw.dxfInt(74, 0);
3633         dw.dxfReal(49, -6.35);
3634         if (version>=VER_R13)
3635             dw.dxfInt(74, 0);
3636     } else if (!strcasecmp(data.name.c_str(), "DASHED2")) {
3637         dw.dxfString(3, "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _");
3638         dw.dxfInt(72, 65);
3639         dw.dxfInt(73, 2);
3640         dw.dxfReal(40, 9.525);
3641         dw.dxfReal(49, 6.35);
3642         if (version>=VER_R13)
3643             dw.dxfInt(74, 0);
3644         dw.dxfReal(49, -3.175);
3645         if (version>=VER_R13)
3646             dw.dxfInt(74, 0);
3647     } else if (!strcasecmp(data.name.c_str(), "DASHEDX2")) {
3648         dw.dxfString(3, "Dashed (2x) ____  ____  ____  ____  ____  ___");
3649         dw.dxfInt(72, 65);
3650         dw.dxfInt(73, 2);
3651         dw.dxfReal(40, 38.1);
3652         dw.dxfReal(49, 25.4);
3653         if (version>=VER_R13)
3654             dw.dxfInt(74, 0);
3655         dw.dxfReal(49, -12.7);
3656         if (version>=VER_R13)
3657             dw.dxfInt(74, 0);
3658     } else if (!strcasecmp(data.name.c_str(), "DIVIDE")) {
3659         dw.dxfString(3, "Divide ____ . . ____ . . ____ . . ____ . . ____");
3660         dw.dxfInt(72, 65);
3661         dw.dxfInt(73, 6);
3662         dw.dxfReal(40, 31.75);
3663         dw.dxfReal(49, 12.7);
3664         if (version>=VER_R13)
3665             dw.dxfInt(74, 0);
3666         dw.dxfReal(49, -6.35);
3667         if (version>=VER_R13)
3668             dw.dxfInt(74, 0);
3669         dw.dxfReal(49, 0.0);
3670         if (version>=VER_R13)
3671             dw.dxfInt(74, 0);
3672         dw.dxfReal(49, -6.35);
3673         if (version>=VER_R13)
3674             dw.dxfInt(74, 0);
3675         dw.dxfReal(49, 0.0);
3676         if (version>=VER_R13)
3677             dw.dxfInt(74, 0);
3678         dw.dxfReal(49, -6.35);
3679         if (version>=VER_R13)
3680             dw.dxfInt(74, 0);
3681     } else if (!strcasecmp(data.name.c_str(), "DIVIDE2")) {
3682         dw.dxfString(3, "Divide (.5x) __..__..__..__..__..__..__..__.._");
3683         dw.dxfInt(72, 65);
3684         dw.dxfInt(73, 6);
3685         dw.dxfReal(40, 15.875);
3686         dw.dxfReal(49, 6.35);
3687         if (version>=VER_R13)
3688             dw.dxfInt(74, 0);
3689         dw.dxfReal(49, -3.175);
3690         if (version>=VER_R13)
3691             dw.dxfInt(74, 0);
3692         dw.dxfReal(49, 0.0);
3693         if (version>=VER_R13)
3694             dw.dxfInt(74, 0);
3695         dw.dxfReal(49, -3.175);
3696         if (version>=VER_R13)
3697             dw.dxfInt(74, 0);
3698         dw.dxfReal(49, 0.0);
3699         if (version>=VER_R13)
3700             dw.dxfInt(74, 0);
3701         dw.dxfReal(49, -3.175);
3702         if (version>=VER_R13)
3703             dw.dxfInt(74, 0);
3704     } else if (!strcasecmp(data.name.c_str(), "DIVIDEX2")) {
3705         dw.dxfString(3, "Divide (2x) ________  .  .  ________  .  .  _");
3706         dw.dxfInt(72, 65);
3707         dw.dxfInt(73, 6);
3708         dw.dxfReal(40, 63.5);
3709         dw.dxfReal(49, 25.4);
3710         if (version>=VER_R13)
3711             dw.dxfInt(74, 0);
3712         dw.dxfReal(49, -12.7);
3713         if (version>=VER_R13)
3714             dw.dxfInt(74, 0);
3715         dw.dxfReal(49, 0.0);
3716         if (version>=VER_R13)
3717             dw.dxfInt(74, 0);
3718         dw.dxfReal(49, -12.7);
3719         if (version>=VER_R13)
3720             dw.dxfInt(74, 0);
3721         dw.dxfReal(49, 0.0);
3722         if (version>=VER_R13)
3723             dw.dxfInt(74, 0);
3724         dw.dxfReal(49, -12.7);
3725         if (version>=VER_R13)
3726             dw.dxfInt(74, 0);
3727     } else if (!strcasecmp(data.name.c_str(), "DOT")) {
3728         dw.dxfString(3, "Dot . . . . . . . . . . . . . . . . . . . . . .");
3729         dw.dxfInt(72, 65);
3730         dw.dxfInt(73, 2);
3731         dw.dxfReal(40, 6.35);
3732         dw.dxfReal(49, 0.0);
3733         if (version>=VER_R13)
3734             dw.dxfInt(74, 0);
3735         dw.dxfReal(49, -6.35);
3736         if (version>=VER_R13)
3737             dw.dxfInt(74, 0);
3738     } else if (!strcasecmp(data.name.c_str(), "DOT2")) {
3739         dw.dxfString(3, "Dot (.5x) .....................................");
3740         dw.dxfInt(72, 65);
3741         dw.dxfInt(73, 2);
3742         dw.dxfReal(40, 3.175);
3743         dw.dxfReal(49, 0.0);
3744         if (version>=VER_R13)
3745             dw.dxfInt(74, 0);
3746         dw.dxfReal(49, -3.175);
3747         if (version>=VER_R13)
3748             dw.dxfInt(74, 0);
3749     } else if (!strcasecmp(data.name.c_str(), "DOTX2")) {
3750         dw.dxfString(3, "Dot (2x) .  .  .  .  .  .  .  .  .  .  .  .  .");
3751         dw.dxfInt(72, 65);
3752         dw.dxfInt(73, 2);
3753         dw.dxfReal(40, 12.7);
3754         dw.dxfReal(49, 0.0);
3755         if (version>=VER_R13)
3756             dw.dxfInt(74, 0);
3757         dw.dxfReal(49, -12.7);
3758         if (version>=VER_R13)
3759             dw.dxfInt(74, 0);
3760     } else {
3761         std::cerr << "dxflib warning: DL_Dxf::writeLineType: Unknown Line Type\n";
3762     }
3763 }
3764 
3765 
3766 
3767 /**
3768  * Writes the APPID section to the DXF file.
3769  *
3770  * @param name Application name
3771  */
writeAppid(DL_WriterA & dw,const string & name)3772 void DL_Dxf::writeAppid(DL_WriterA& dw, const string& name) {
3773     if (name.empty()) {
3774         std::cerr << "DL_Dxf::writeAppid: "
3775         << "Application  name must not be empty\n";
3776         return;
3777     }
3778 
3779     if (!strcasecmp(name.c_str(), "ACAD")) {
3780         dw.tableAppidEntry(0x12);
3781     } else {
3782         dw.tableAppidEntry();
3783     }
3784     dw.dxfString(2, name);
3785     dw.dxfInt(70, 0);
3786 }
3787 
3788 
3789 
3790 /**
3791  * Writes a block's definition (no entities) to the DXF file.
3792  */
writeBlock(DL_WriterA & dw,const DL_BlockData & data)3793 void DL_Dxf::writeBlock(DL_WriterA& dw, const DL_BlockData& data) {
3794     if (data.name.empty()) {
3795         std::cerr << "DL_Dxf::writeBlock: "
3796         << "Block name must not be empty\n";
3797         return;
3798     }
3799 
3800     //bool paperSpace = !strcasecmp(name, "*paper_space");
3801     //!strcasecmp(name, "*paper_space0");
3802 
3803     if (!strcasecmp(data.name.c_str(), "*paper_space")) {
3804         dw.sectionBlockEntry(0x1C);
3805     } else if (!strcasecmp(data.name.c_str(), "*model_space")) {
3806         dw.sectionBlockEntry(0x20);
3807     } else if (!strcasecmp(data.name.c_str(), "*paper_space0")) {
3808         dw.sectionBlockEntry(0x24);
3809     } else {
3810         dw.sectionBlockEntry();
3811     }
3812     dw.dxfString(2, data.name);
3813     dw.dxfInt(70, 0);
3814     dw.coord(10, data.bpx, data.bpy);
3815     dw.dxfString(3, data.name);
3816     dw.dxfString(1, "");
3817 }
3818 
3819 
3820 
3821 /**
3822  * Writes a block end.
3823  *
3824  * @param name Block name
3825  */
writeEndBlock(DL_WriterA & dw,const string & name)3826 void DL_Dxf::writeEndBlock(DL_WriterA& dw, const string& name) {
3827     if (!strcasecmp(name.c_str(), "*paper_space")) {
3828         dw.sectionBlockEntryEnd(0x1D);
3829     } else if (!strcasecmp(name.c_str(), "*model_space")) {
3830         dw.sectionBlockEntryEnd(0x21);
3831     } else if (!strcasecmp(name.c_str(), "*paper_space0")) {
3832         dw.sectionBlockEntryEnd(0x25);
3833     } else {
3834         dw.sectionBlockEntryEnd();
3835     }
3836 }
3837 
3838 
3839 
3840 /**
3841  * Writes a viewport section. This section is needed in VER_R13.
3842  * Note that this method currently only writes a faked VPORT section
3843  * to make the file readable by Aut*cad.
3844  */
writeVPort(DL_WriterA & dw)3845 void DL_Dxf::writeVPort(DL_WriterA& dw) {
3846     dw.dxfString(0, "TABLE");
3847     dw.dxfString(2, "VPORT");
3848     if (version==VER_2000) {
3849         dw.dxfHex(5, 0x8);
3850     }
3851     //dw.dxfHex(330, 0);
3852     if (version==VER_2000) {
3853         dw.dxfString(100, "AcDbSymbolTable");
3854     }
3855     dw.dxfInt(70, 1);
3856     dw.dxfString(0, "VPORT");
3857     //dw.dxfHex(5, 0x2F);
3858     if (version==VER_2000) {
3859         dw.handle();
3860     }
3861     //dw.dxfHex(330, 8);
3862     if (version==VER_2000) {
3863         dw.dxfString(100, "AcDbSymbolTableRecord");
3864         dw.dxfString(100, "AcDbViewportTableRecord");
3865     }
3866     dw.dxfString(  2, "*Active");
3867     dw.dxfInt( 70, 0);
3868     dw.dxfReal( 10, 0.0);
3869     dw.dxfReal( 20, 0.0);
3870     dw.dxfReal( 11, 1.0);
3871     dw.dxfReal( 21, 1.0);
3872     dw.dxfReal( 12, 286.3055555555555);
3873     dw.dxfReal( 22, 148.5);
3874     dw.dxfReal( 13, 0.0);
3875     dw.dxfReal( 23, 0.0);
3876     dw.dxfReal( 14, 10.0);
3877     dw.dxfReal( 24, 10.0);
3878     dw.dxfReal( 15, 10.0);
3879     dw.dxfReal( 25, 10.0);
3880     dw.dxfReal( 16, 0.0);
3881     dw.dxfReal( 26, 0.0);
3882     dw.dxfReal( 36, 1.0);
3883     dw.dxfReal( 17, 0.0);
3884     dw.dxfReal( 27, 0.0);
3885     dw.dxfReal( 37, 0.0);
3886     dw.dxfReal( 40, 297.0);
3887     dw.dxfReal( 41, 1.92798353909465);
3888     dw.dxfReal( 42, 50.0);
3889     dw.dxfReal( 43, 0.0);
3890     dw.dxfReal( 44, 0.0);
3891     dw.dxfReal( 50, 0.0);
3892     dw.dxfReal( 51, 0.0);
3893     dw.dxfInt( 71, 0);
3894     dw.dxfInt( 72, 100);
3895     dw.dxfInt( 73, 1);
3896     dw.dxfInt( 74, 3);
3897     dw.dxfInt( 75, 1);
3898     dw.dxfInt( 76, 1);
3899     dw.dxfInt( 77, 0);
3900     dw.dxfInt( 78, 0);
3901 
3902     if (version==VER_2000) {
3903         dw.dxfInt(281, 0);
3904         dw.dxfInt( 65, 1);
3905         dw.dxfReal(110, 0.0);
3906         dw.dxfReal(120, 0.0);
3907         dw.dxfReal(130, 0.0);
3908         dw.dxfReal(111, 1.0);
3909         dw.dxfReal(121, 0.0);
3910         dw.dxfReal(131, 0.0);
3911         dw.dxfReal(112, 0.0);
3912         dw.dxfReal(122, 1.0);
3913         dw.dxfReal(132, 0.0);
3914         dw.dxfInt( 79, 0);
3915         dw.dxfReal(146, 0.0);
3916     }
3917     dw.dxfString(  0, "ENDTAB");
3918 }
3919 
3920 
3921 
3922 /**
3923  * Writes a style section. This section is needed in VER_R13.
3924  * Note that this method currently only writes a faked STYLE section
3925  * to make the file readable by Aut*cad.
3926  */
writeStyle(DL_WriterA & dw)3927 void DL_Dxf::writeStyle(DL_WriterA& dw) {
3928     dw.dxfString(  0, "TABLE");
3929     dw.dxfString(  2, "STYLE");
3930     if (version==VER_2000) {
3931     	dw.dxfHex(5, 3);
3932 	}
3933     //dw.dxfHex(330, 0);
3934     if (version==VER_2000) {
3935         dw.dxfString(100, "AcDbSymbolTable");
3936     }
3937     dw.dxfInt( 70, 1);
3938     dw.dxfString(  0, "STYLE");
3939     if (version==VER_2000) {
3940     	dw.dxfHex(5, 0x11);
3941 	}
3942     //styleHandleStd = dw.handle();
3943     //dw.dxfHex(330, 3);
3944     if (version==VER_2000) {
3945         dw.dxfString(100, "AcDbSymbolTableRecord");
3946         dw.dxfString(100, "AcDbTextStyleTableRecord");
3947     }
3948     dw.dxfString(  2, "Standard");
3949     dw.dxfInt( 70, 0);
3950     dw.dxfReal( 40, 0.0);
3951     dw.dxfReal( 41, 0.75);
3952     dw.dxfReal( 50, 0.0);
3953     dw.dxfInt( 71, 0);
3954     dw.dxfReal( 42, 2.5);
3955     dw.dxfString(  3, "txt");
3956     dw.dxfString(  4, "");
3957     dw.dxfString(  0, "ENDTAB");
3958 }
3959 
3960 
3961 
3962 /**
3963  * Writes a view section. This section is needed in VER_R13.
3964  * Note that this method currently only writes a faked VIEW section
3965  * to make the file readable by Aut*cad.
3966  */
writeView(DL_WriterA & dw)3967 void DL_Dxf::writeView(DL_WriterA& dw) {
3968     dw.dxfString(  0, "TABLE");
3969     dw.dxfString(  2, "VIEW");
3970     if (version==VER_2000) {
3971     	dw.dxfHex(5, 6);
3972 	}
3973     //dw.dxfHex(330, 0);
3974     if (version==VER_2000) {
3975         dw.dxfString(100, "AcDbSymbolTable");
3976     }
3977     dw.dxfInt( 70, 0);
3978     dw.dxfString(  0, "ENDTAB");
3979 }
3980 
3981 
3982 
3983 /**
3984  * Writes a ucs section. This section is needed in VER_R13.
3985  * Note that this method currently only writes a faked UCS section
3986  * to make the file readable by Aut*cad.
3987  */
writeUcs(DL_WriterA & dw)3988 void DL_Dxf::writeUcs(DL_WriterA& dw) {
3989     dw.dxfString(  0, "TABLE");
3990     dw.dxfString(  2, "UCS");
3991     if (version==VER_2000) {
3992     	dw.dxfHex(5, 7);
3993 	}
3994     //dw.dxfHex(330, 0);
3995     if (version==VER_2000) {
3996         dw.dxfString(100, "AcDbSymbolTable");
3997     }
3998     dw.dxfInt( 70, 0);
3999     dw.dxfString(  0, "ENDTAB");
4000 }
4001 
4002 
4003 
4004 /**
4005  * Writes a dimstyle section. This section is needed in VER_R13.
4006  * Note that this method currently only writes a faked DIMSTYLE section
4007  * to make the file readable by Aut*cad.
4008  */
writeDimStyle(DL_WriterA & dw,double dimasz,double dimexe,double dimexo,double dimgap,double dimtxt)4009 void DL_Dxf::writeDimStyle(DL_WriterA& dw,
4010 					double dimasz, double dimexe, double dimexo,
4011                        double dimgap, double dimtxt) {
4012 
4013     dw.dxfString(  0, "TABLE");
4014     dw.dxfString(  2, "DIMSTYLE");
4015     if (version==VER_2000) {
4016         dw.dxfHex(5, 0xA);
4017         dw.dxfString(100, "AcDbSymbolTable");
4018     }
4019     dw.dxfInt( 70, 1);
4020     if (version==VER_2000) {
4021         dw.dxfString(100, "AcDbDimStyleTable");
4022         dw.dxfInt( 71, 0);
4023     }
4024 
4025 
4026     dw.dxfString(  0, "DIMSTYLE");
4027     if (version==VER_2000) {
4028         dw.dxfHex(105, 0x27);
4029     }
4030     //dw.handle(105);
4031     //dw.dxfHex(330, 0xA);
4032     if (version==VER_2000) {
4033         dw.dxfString(100, "AcDbSymbolTableRecord");
4034         dw.dxfString(100, "AcDbDimStyleTableRecord");
4035     }
4036     dw.dxfString(  2, "Standard");
4037     if (version==VER_R12) {
4038         dw.dxfString(  3, "");
4039         dw.dxfString(  4, "");
4040         dw.dxfString(  5, "");
4041         dw.dxfString(  6, "");
4042         dw.dxfString(  7, "");
4043         dw.dxfReal( 40, 1.0);
4044     }
4045 
4046     dw.dxfReal( 41, dimasz);
4047     dw.dxfReal( 42, dimexo);
4048     dw.dxfReal( 43, 3.75);
4049     dw.dxfReal( 44, dimexe);
4050     if (version==VER_R12) {
4051         dw.dxfReal( 45, 0.0);
4052         dw.dxfReal( 46, 0.0);
4053         dw.dxfReal( 47, 0.0);
4054         dw.dxfReal( 48, 0.0);
4055     }
4056     dw.dxfInt( 70, 0);
4057     if (version==VER_R12) {
4058         dw.dxfInt( 71, 0);
4059         dw.dxfInt( 72, 0);
4060     }
4061     dw.dxfInt( 73, 0);
4062     dw.dxfInt( 74, 0);
4063     if (version==VER_R12) {
4064         dw.dxfInt( 75, 0);
4065         dw.dxfInt( 76, 0);
4066     }
4067     dw.dxfInt( 77, 1);
4068     dw.dxfInt( 78, 8);
4069     dw.dxfReal(140, dimtxt);
4070     dw.dxfReal(141, 2.5);
4071     if (version==VER_R12) {
4072         dw.dxfReal(142, 0.0);
4073     }
4074     dw.dxfReal(143, 0.03937007874016);
4075     if (version==VER_R12) {
4076         dw.dxfReal(144, 1.0);
4077         dw.dxfReal(145, 0.0);
4078         dw.dxfReal(146, 1.0);
4079     }
4080     dw.dxfReal(147, dimgap);
4081     if (version==VER_R12) {
4082         dw.dxfInt(170, 0);
4083     }
4084     dw.dxfInt(171, 3);
4085     dw.dxfInt(172, 1);
4086     if (version==VER_R12) {
4087         dw.dxfInt(173, 0);
4088         dw.dxfInt(174, 0);
4089         dw.dxfInt(175, 0);
4090         dw.dxfInt(176, 0);
4091         dw.dxfInt(177, 0);
4092         dw.dxfInt(178, 0);
4093     }
4094     if (version==VER_2000) {
4095         dw.dxfInt(271, 2);
4096         dw.dxfInt(272, 2);
4097         dw.dxfInt(274, 3);
4098         dw.dxfInt(278, 44);
4099         dw.dxfInt(283, 0);
4100         dw.dxfInt(284, 8);
4101         //dw.dxfHex(340, styleHandleStd);
4102         dw.dxfHex(340, 0x11);
4103     }
4104     // * /
4105     dw.dxfString(  0, "ENDTAB");
4106 }
4107 
4108 
4109 
4110 /**
4111  * Writes a blockrecord section. This section is needed in VER_R13.
4112  * Note that this method currently only writes a faked BLOCKRECORD section
4113  * to make the file readable by Aut*cad.
4114  */
writeBlockRecord(DL_WriterA & dw)4115 void DL_Dxf::writeBlockRecord(DL_WriterA& dw) {
4116     dw.dxfString(  0, "TABLE");
4117     dw.dxfString(  2, "BLOCK_RECORD");
4118     if (version==VER_2000) {
4119     	dw.dxfHex(5, 1);
4120 	}
4121     //dw.dxfHex(330, 0);
4122     if (version==VER_2000) {
4123         dw.dxfString(100, "AcDbSymbolTable");
4124     }
4125     dw.dxfInt( 70, 1);
4126 
4127     dw.dxfString(  0, "BLOCK_RECORD");
4128     if (version==VER_2000) {
4129     	dw.dxfHex(5, 0x1F);
4130 	}
4131     //int msh = dw.handle();
4132     //dw.setModelSpaceHandle(msh);
4133     //dw.dxfHex(330, 1);
4134     if (version==VER_2000) {
4135         dw.dxfString(100, "AcDbSymbolTableRecord");
4136         dw.dxfString(100, "AcDbBlockTableRecord");
4137     }
4138     dw.dxfString(  2, "*Model_Space");
4139     dw.dxfHex(340, 0x22);
4140 
4141     dw.dxfString(  0, "BLOCK_RECORD");
4142     if (version==VER_2000) {
4143     	dw.dxfHex(5, 0x1B);
4144 	}
4145     //int psh = dw.handle();
4146     //dw.setPaperSpaceHandle(psh);
4147     //dw.dxfHex(330, 1);
4148     if (version==VER_2000) {
4149         dw.dxfString(100, "AcDbSymbolTableRecord");
4150         dw.dxfString(100, "AcDbBlockTableRecord");
4151     }
4152     dw.dxfString(  2, "*Paper_Space");
4153     dw.dxfHex(340, 0x1E);
4154 
4155     dw.dxfString(  0, "BLOCK_RECORD");
4156     if (version==VER_2000) {
4157     	dw.dxfHex(5, 0x23);
4158 	}
4159     //int ps0h = dw.handle();
4160     //dw.setPaperSpace0Handle(ps0h);
4161     //dw.dxfHex(330, 1);
4162     if (version==VER_2000) {
4163         dw.dxfString(100, "AcDbSymbolTableRecord");
4164         dw.dxfString(100, "AcDbBlockTableRecord");
4165     }
4166     dw.dxfString(  2, "*Paper_Space0");
4167     dw.dxfHex(340, 0x26);
4168 
4169     //dw.dxfString(  0, "ENDTAB");
4170 }
4171 
4172 
4173 
4174 /**
4175  * Writes a single block record with the given name.
4176  */
writeBlockRecord(DL_WriterA & dw,const string & name)4177 void DL_Dxf::writeBlockRecord(DL_WriterA& dw, const string& name) {
4178     dw.dxfString(  0, "BLOCK_RECORD");
4179     if (version==VER_2000) {
4180     	dw.handle();
4181 	}
4182     //dw->dxfHex(330, 1);
4183     if (version==VER_2000) {
4184         dw.dxfString(100, "AcDbSymbolTableRecord");
4185         dw.dxfString(100, "AcDbBlockTableRecord");
4186     }
4187     dw.dxfString(  2, name);
4188     dw.dxfHex(340, 0);
4189 }
4190 
4191 
4192 
4193 /**
4194  * Writes a objects section. This section is needed in VER_R13.
4195  * Note that this method currently only writes a faked OBJECTS section
4196  * to make the file readable by Aut*cad.
4197  */
writeObjects(DL_WriterA & dw)4198 void DL_Dxf::writeObjects(DL_WriterA& dw) {
4199     //int dicId, dicId2, dicId3, dicId4, dicId5;
4200     //int dicId5;
4201 
4202     dw.dxfString(  0, "SECTION");
4203     dw.dxfString(  2, "OBJECTS");
4204     dw.dxfString(  0, "DICTIONARY");
4205     dw.dxfHex(5, 0xC);                            // C
4206     //dw.dxfHex(330, 0);
4207     dw.dxfString(100, "AcDbDictionary");
4208     dw.dxfInt(280, 0);
4209     dw.dxfInt(281, 1);
4210     dw.dxfString(  3, "ACAD_GROUP");
4211     //dw.dxfHex(350, dw.getNextHandle());          // D
4212     dw.dxfHex(350, 0xD);          // D
4213     dw.dxfString(  3, "ACAD_LAYOUT");
4214     dw.dxfHex(350, 0x1A);
4215     //dw.dxfHex(350, dw.getNextHandle()+0);        // 1A
4216     dw.dxfString(  3, "ACAD_MLINESTYLE");
4217     dw.dxfHex(350, 0x17);
4218     //dw.dxfHex(350, dw.getNextHandle()+1);        // 17
4219     dw.dxfString(  3, "ACAD_PLOTSETTINGS");
4220     dw.dxfHex(350, 0x19);
4221     //dw.dxfHex(350, dw.getNextHandle()+2);        // 19
4222     dw.dxfString(  3, "ACAD_PLOTSTYLENAME");
4223     dw.dxfHex(350, 0xE);
4224     //dw.dxfHex(350, dw.getNextHandle()+3);        // E
4225     dw.dxfString(  3, "AcDbVariableDictionary");
4226     dw.dxfHex(350, dw.getNextHandle());        // 2C
4227     dw.dxfString(  0, "DICTIONARY");
4228     dw.dxfHex(5, 0xD);
4229     //dw.handle();                                    // D
4230     //dw.dxfHex(330, 0xC);
4231     dw.dxfString(100, "AcDbDictionary");
4232     dw.dxfInt(280, 0);
4233     dw.dxfInt(281, 1);
4234     dw.dxfString(  0, "ACDBDICTIONARYWDFLT");
4235     dw.dxfHex(5, 0xE);
4236     //dicId4 = dw.handle();                           // E
4237     //dw.dxfHex(330, 0xC);                       // C
4238     dw.dxfString(100, "AcDbDictionary");
4239     dw.dxfInt(281, 1);
4240     dw.dxfString(  3, "Normal");
4241     dw.dxfHex(350, 0xF);
4242     //dw.dxfHex(350, dw.getNextHandle()+5);        // F
4243     dw.dxfString(100, "AcDbDictionaryWithDefault");
4244     dw.dxfHex(340, 0xF);
4245     //dw.dxfHex(340, dw.getNextHandle()+5);        // F
4246     dw.dxfString(  0, "ACDBPLACEHOLDER");
4247     dw.dxfHex(5, 0xF);
4248     //dw.handle();                                    // F
4249     //dw.dxfHex(330, dicId4);                      // E
4250     dw.dxfString(  0, "DICTIONARY");
4251     //dicId3 = dw.handle();                           // 17
4252     dw.dxfHex(5, 0x17);
4253     //dw.dxfHex(330, 0xC);                       // C
4254     dw.dxfString(100, "AcDbDictionary");
4255     dw.dxfInt(280, 0);
4256     dw.dxfInt(281, 1);
4257     dw.dxfString(  3, "Standard");
4258     dw.dxfHex(350, 0x18);
4259     //dw.dxfHex(350, dw.getNextHandle()+5);        // 18
4260     dw.dxfString(  0, "MLINESTYLE");
4261     dw.dxfHex(5, 0x18);
4262     //dw.handle();                                    // 18
4263     //dw.dxfHex(330, dicId3);                      // 17
4264     dw.dxfString(100, "AcDbMlineStyle");
4265     dw.dxfString(  2, "STANDARD");
4266     dw.dxfInt( 70, 0);
4267     dw.dxfString(  3, "");
4268     dw.dxfInt( 62, 256);
4269     dw.dxfReal( 51, 90.0);
4270     dw.dxfReal( 52, 90.0);
4271     dw.dxfInt( 71, 2);
4272     dw.dxfReal( 49, 0.5);
4273     dw.dxfInt( 62, 256);
4274     dw.dxfString(  6, "BYLAYER");
4275     dw.dxfReal( 49, -0.5);
4276     dw.dxfInt( 62, 256);
4277     dw.dxfString(  6, "BYLAYER");
4278     dw.dxfString(  0, "DICTIONARY");
4279     dw.dxfHex(5, 0x19);
4280     //dw.handle();                           // 17
4281     //dw.dxfHex(330, 0xC);                       // C
4282     dw.dxfString(100, "AcDbDictionary");
4283     dw.dxfInt(280, 0);
4284     dw.dxfInt(281, 1);
4285     dw.dxfString(  0, "DICTIONARY");
4286     //dicId2 = dw.handle();                           // 1A
4287     dw.dxfHex(5, 0x1A);
4288     //dw.dxfHex(330, 0xC);
4289     dw.dxfString(100, "AcDbDictionary");
4290     dw.dxfInt(281, 1);
4291     dw.dxfString(  3, "Layout1");
4292     dw.dxfHex(350, 0x1E);
4293     //dw.dxfHex(350, dw.getNextHandle()+2);        // 1E
4294     dw.dxfString(  3, "Layout2");
4295     dw.dxfHex(350, 0x26);
4296     //dw.dxfHex(350, dw.getNextHandle()+4);        // 26
4297     dw.dxfString(  3, "Model");
4298     dw.dxfHex(350, 0x22);
4299     //dw.dxfHex(350, dw.getNextHandle()+5);        // 22
4300 
4301     dw.dxfString(  0, "LAYOUT");
4302     dw.dxfHex(5, 0x1E);
4303     //dw.handle();                                    // 1E
4304     //dw.dxfHex(330, dicId2);                      // 1A
4305     dw.dxfString(100, "AcDbPlotSettings");
4306     dw.dxfString(  1, "");
4307     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4308     dw.dxfString(  4, "");
4309     dw.dxfString(  6, "");
4310     dw.dxfReal( 40, 0.0);
4311     dw.dxfReal( 41, 0.0);
4312     dw.dxfReal( 42, 0.0);
4313     dw.dxfReal( 43, 0.0);
4314     dw.dxfReal( 44, 0.0);
4315     dw.dxfReal( 45, 0.0);
4316     dw.dxfReal( 46, 0.0);
4317     dw.dxfReal( 47, 0.0);
4318     dw.dxfReal( 48, 0.0);
4319     dw.dxfReal( 49, 0.0);
4320     dw.dxfReal(140, 0.0);
4321     dw.dxfReal(141, 0.0);
4322     dw.dxfReal(142, 1.0);
4323     dw.dxfReal(143, 1.0);
4324     dw.dxfInt( 70, 688);
4325     dw.dxfInt( 72, 0);
4326     dw.dxfInt( 73, 0);
4327     dw.dxfInt( 74, 5);
4328     dw.dxfString(  7, "");
4329     dw.dxfInt( 75, 16);
4330     dw.dxfReal(147, 1.0);
4331     dw.dxfReal(148, 0.0);
4332     dw.dxfReal(149, 0.0);
4333     dw.dxfString(100, "AcDbLayout");
4334     dw.dxfString(  1, "Layout1");
4335     dw.dxfInt( 70, 1);
4336     dw.dxfInt( 71, 1);
4337     dw.dxfReal( 10, 0.0);
4338     dw.dxfReal( 20, 0.0);
4339     dw.dxfReal( 11, 420.0);
4340     dw.dxfReal( 21, 297.0);
4341     dw.dxfReal( 12, 0.0);
4342     dw.dxfReal( 22, 0.0);
4343     dw.dxfReal( 32, 0.0);
4344     dw.dxfReal( 14, 1.000000000000000E+20);
4345     dw.dxfReal( 24, 1.000000000000000E+20);
4346     dw.dxfReal( 34, 1.000000000000000E+20);
4347     dw.dxfReal( 15, -1.000000000000000E+20);
4348     dw.dxfReal( 25, -1.000000000000000E+20);
4349     dw.dxfReal( 35, -1.000000000000000E+20);
4350     dw.dxfReal(146, 0.0);
4351     dw.dxfReal( 13, 0.0);
4352     dw.dxfReal( 23, 0.0);
4353     dw.dxfReal( 33, 0.0);
4354     dw.dxfReal( 16, 1.0);
4355     dw.dxfReal( 26, 0.0);
4356     dw.dxfReal( 36, 0.0);
4357     dw.dxfReal( 17, 0.0);
4358     dw.dxfReal( 27, 1.0);
4359     dw.dxfReal( 37, 0.0);
4360     dw.dxfInt( 76, 0);
4361     //dw.dxfHex(330, dw.getPaperSpaceHandle());    // 1B
4362     dw.dxfHex(330, 0x1B);
4363     dw.dxfString(  0, "LAYOUT");
4364     dw.dxfHex(5, 0x22);
4365     //dw.handle();                                    // 22
4366     //dw.dxfHex(330, dicId2);                      // 1A
4367     dw.dxfString(100, "AcDbPlotSettings");
4368     dw.dxfString(  1, "");
4369     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4370     dw.dxfString(  4, "");
4371     dw.dxfString(  6, "");
4372     dw.dxfReal( 40, 0.0);
4373     dw.dxfReal( 41, 0.0);
4374     dw.dxfReal( 42, 0.0);
4375     dw.dxfReal( 43, 0.0);
4376     dw.dxfReal( 44, 0.0);
4377     dw.dxfReal( 45, 0.0);
4378     dw.dxfReal( 46, 0.0);
4379     dw.dxfReal( 47, 0.0);
4380     dw.dxfReal( 48, 0.0);
4381     dw.dxfReal( 49, 0.0);
4382     dw.dxfReal(140, 0.0);
4383     dw.dxfReal(141, 0.0);
4384     dw.dxfReal(142, 1.0);
4385     dw.dxfReal(143, 1.0);
4386     dw.dxfInt( 70, 1712);
4387     dw.dxfInt( 72, 0);
4388     dw.dxfInt( 73, 0);
4389     dw.dxfInt( 74, 0);
4390     dw.dxfString(  7, "");
4391     dw.dxfInt( 75, 0);
4392     dw.dxfReal(147, 1.0);
4393     dw.dxfReal(148, 0.0);
4394     dw.dxfReal(149, 0.0);
4395     dw.dxfString(100, "AcDbLayout");
4396     dw.dxfString(  1, "Model");
4397     dw.dxfInt( 70, 1);
4398     dw.dxfInt( 71, 0);
4399     dw.dxfReal( 10, 0.0);
4400     dw.dxfReal( 20, 0.0);
4401     dw.dxfReal( 11, 12.0);
4402     dw.dxfReal( 21, 9.0);
4403     dw.dxfReal( 12, 0.0);
4404     dw.dxfReal( 22, 0.0);
4405     dw.dxfReal( 32, 0.0);
4406     dw.dxfReal( 14, 0.0);
4407     dw.dxfReal( 24, 0.0);
4408     dw.dxfReal( 34, 0.0);
4409     dw.dxfReal( 15, 0.0);
4410     dw.dxfReal( 25, 0.0);
4411     dw.dxfReal( 35, 0.0);
4412     dw.dxfReal(146, 0.0);
4413     dw.dxfReal( 13, 0.0);
4414     dw.dxfReal( 23, 0.0);
4415     dw.dxfReal( 33, 0.0);
4416     dw.dxfReal( 16, 1.0);
4417     dw.dxfReal( 26, 0.0);
4418     dw.dxfReal( 36, 0.0);
4419     dw.dxfReal( 17, 0.0);
4420     dw.dxfReal( 27, 1.0);
4421     dw.dxfReal( 37, 0.0);
4422     dw.dxfInt( 76, 0);
4423     //dw.dxfHex(330, dw.getModelSpaceHandle());    // 1F
4424     dw.dxfHex(330, 0x1F);
4425     dw.dxfString(  0, "LAYOUT");
4426     //dw.handle();                                    // 26
4427     dw.dxfHex(5, 0x26);
4428     //dw.dxfHex(330, dicId2);                      // 1A
4429     dw.dxfString(100, "AcDbPlotSettings");
4430     dw.dxfString(  1, "");
4431     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4432     dw.dxfString(  4, "");
4433     dw.dxfString(  6, "");
4434     dw.dxfReal( 40, 0.0);
4435     dw.dxfReal( 41, 0.0);
4436     dw.dxfReal( 42, 0.0);
4437     dw.dxfReal( 43, 0.0);
4438     dw.dxfReal( 44, 0.0);
4439     dw.dxfReal( 45, 0.0);
4440     dw.dxfReal( 46, 0.0);
4441     dw.dxfReal( 47, 0.0);
4442     dw.dxfReal( 48, 0.0);
4443     dw.dxfReal( 49, 0.0);
4444     dw.dxfReal(140, 0.0);
4445     dw.dxfReal(141, 0.0);
4446     dw.dxfReal(142, 1.0);
4447     dw.dxfReal(143, 1.0);
4448     dw.dxfInt( 70, 688);
4449     dw.dxfInt( 72, 0);
4450     dw.dxfInt( 73, 0);
4451     dw.dxfInt( 74, 5);
4452     dw.dxfString(  7, "");
4453     dw.dxfInt( 75, 16);
4454     dw.dxfReal(147, 1.0);
4455     dw.dxfReal(148, 0.0);
4456     dw.dxfReal(149, 0.0);
4457     dw.dxfString(100, "AcDbLayout");
4458     dw.dxfString(  1, "Layout2");
4459     dw.dxfInt( 70, 1);
4460     dw.dxfInt( 71, 2);
4461     dw.dxfReal( 10, 0.0);
4462     dw.dxfReal( 20, 0.0);
4463     dw.dxfReal( 11, 12.0);
4464     dw.dxfReal( 21, 9.0);
4465     dw.dxfReal( 12, 0.0);
4466     dw.dxfReal( 22, 0.0);
4467     dw.dxfReal( 32, 0.0);
4468     dw.dxfReal( 14, 0.0);
4469     dw.dxfReal( 24, 0.0);
4470     dw.dxfReal( 34, 0.0);
4471     dw.dxfReal( 15, 0.0);
4472     dw.dxfReal( 25, 0.0);
4473     dw.dxfReal( 35, 0.0);
4474     dw.dxfReal(146, 0.0);
4475     dw.dxfReal( 13, 0.0);
4476     dw.dxfReal( 23, 0.0);
4477     dw.dxfReal( 33, 0.0);
4478     dw.dxfReal( 16, 1.0);
4479     dw.dxfReal( 26, 0.0);
4480     dw.dxfReal( 36, 0.0);
4481     dw.dxfReal( 17, 0.0);
4482     dw.dxfReal( 27, 1.0);
4483     dw.dxfReal( 37, 0.0);
4484     dw.dxfInt( 76, 0);
4485     //dw.dxfHex(330, dw.getPaperSpace0Handle());   // 23
4486     dw.dxfHex(330, 0x23);
4487     dw.dxfString(  0, "DICTIONARY");
4488     //dw.dxfHex(5, 0x2C);
4489     //dicId5 =
4490     dw.handle();                           // 2C
4491     //dw.dxfHex(330, 0xC);                       // C
4492     dw.dxfString(100, "AcDbDictionary");
4493     dw.dxfInt(281, 1);
4494     dw.dxfString(  3, "DIMASSOC");
4495     //dw.dxfHex(350, 0x2F);
4496     dw.dxfHex(350, dw.getNextHandle()+1);        // 2E
4497     dw.dxfString(  3, "HIDETEXT");
4498     //dw.dxfHex(350, 0x2E);
4499     dw.dxfHex(350, dw.getNextHandle());        // 2D
4500     dw.dxfString(  0, "DICTIONARYVAR");
4501     //dw.dxfHex(5, 0x2E);
4502     dw.handle();                                    // 2E
4503     //dw.dxfHex(330, dicId5);                      // 2C
4504     dw.dxfString(100, "DictionaryVariables");
4505     dw.dxfInt(280, 0);
4506     dw.dxfInt(  1, 2);
4507     dw.dxfString(  0, "DICTIONARYVAR");
4508     //dw.dxfHex(5, 0x2D);
4509     dw.handle();                                    // 2D
4510     //dw.dxfHex(330, dicId5);                      // 2C
4511     dw.dxfString(100, "DictionaryVariables");
4512     dw.dxfInt(280, 0);
4513     dw.dxfInt(  1, 1);
4514 }
4515 
4516 
4517 /**
4518  * Writes the end of the objects section. This section is needed in VER_R13.
4519  * Note that this method currently only writes a faked OBJECTS section
4520  * to make the file readable by Aut*cad.
4521  */
writeObjectsEnd(DL_WriterA & dw)4522 void DL_Dxf::writeObjectsEnd(DL_WriterA& dw) {
4523     dw.dxfString(  0, "ENDSEC");
4524 }
4525 
4526 
4527 
4528 /**
4529  * Writes a comment to the DXF file.
4530  */
writeComment(DL_WriterA & dw,const string & comment)4531 void DL_Dxf::writeComment(DL_WriterA& dw, const string& comment) {
4532     dw.dxfString(999, comment);
4533 }
4534 
4535 
4536 /**
4537  * Checks if the given variable is known by the given DXF version.
4538  */
checkVariable(const char * var,DL_Codes::version version)4539 bool DL_Dxf::checkVariable(const char* var, DL_Codes::version version) {
4540     if (version>=VER_2000) {
4541         return true;
4542     } else if (version==VER_R12) {
4543         // these are all the variables recognized by dxf r12:
4544         if (!strcmp(var, "$ACADVER")) {
4545             return true;
4546         }
4547         if (!strcmp(var, "$ACADVER")) {
4548             return true;
4549         }
4550         if (!strcmp(var, "$ANGBASE")) {
4551             return true;
4552         }
4553         if (!strcmp(var, "$ANGDIR")) {
4554             return true;
4555         }
4556         if (!strcmp(var, "$ATTDIA")) {
4557             return true;
4558         }
4559         if (!strcmp(var, "$ATTMODE")) {
4560             return true;
4561         }
4562         if (!strcmp(var, "$ATTREQ")) {
4563             return true;
4564         }
4565         if (!strcmp(var, "$AUNITS")) {
4566             return true;
4567         }
4568         if (!strcmp(var, "$AUPREC")) {
4569             return true;
4570         }
4571         if (!strcmp(var, "$AXISMODE")) {
4572             return true;
4573         }
4574         if (!strcmp(var, "$AXISUNIT")) {
4575             return true;
4576         }
4577         if (!strcmp(var, "$BLIPMODE")) {
4578             return true;
4579         }
4580         if (!strcmp(var, "$CECOLOR")) {
4581             return true;
4582         }
4583         if (!strcmp(var, "$CELTYPE")) {
4584             return true;
4585         }
4586         if (!strcmp(var, "$CHAMFERA")) {
4587             return true;
4588         }
4589         if (!strcmp(var, "$CHAMFERB")) {
4590             return true;
4591         }
4592         if (!strcmp(var, "$CLAYER")) {
4593             return true;
4594         }
4595         if (!strcmp(var, "$COORDS")) {
4596             return true;
4597         }
4598         if (!strcmp(var, "$DIMALT")) {
4599             return true;
4600         }
4601         if (!strcmp(var, "$DIMALTD")) {
4602             return true;
4603         }
4604         if (!strcmp(var, "$DIMALTF")) {
4605             return true;
4606         }
4607         if (!strcmp(var, "$DIMAPOST")) {
4608             return true;
4609         }
4610         if (!strcmp(var, "$DIMASO")) {
4611             return true;
4612         }
4613         if (!strcmp(var, "$DIMASZ")) {
4614             return true;
4615         }
4616         if (!strcmp(var, "$DIMBLK")) {
4617             return true;
4618         }
4619         if (!strcmp(var, "$DIMBLK1")) {
4620             return true;
4621         }
4622         if (!strcmp(var, "$DIMBLK2")) {
4623             return true;
4624         }
4625         if (!strcmp(var, "$DIMCEN")) {
4626             return true;
4627         }
4628         if (!strcmp(var, "$DIMCLRD")) {
4629             return true;
4630         }
4631         if (!strcmp(var, "$DIMCLRE")) {
4632             return true;
4633         }
4634         if (!strcmp(var, "$DIMCLRT")) {
4635             return true;
4636         }
4637         if (!strcmp(var, "$DIMDLE")) {
4638             return true;
4639         }
4640         if (!strcmp(var, "$DIMDLI")) {
4641             return true;
4642         }
4643         if (!strcmp(var, "$DIMEXE")) {
4644             return true;
4645         }
4646         if (!strcmp(var, "$DIMEXO")) {
4647             return true;
4648         }
4649         if (!strcmp(var, "$DIMGAP")) {
4650             return true;
4651         }
4652         if (!strcmp(var, "$DIMLFAC")) {
4653             return true;
4654         }
4655         if (!strcmp(var, "$DIMLIM")) {
4656             return true;
4657         }
4658         if (!strcmp(var, "$DIMPOST")) {
4659             return true;
4660         }
4661         if (!strcmp(var, "$DIMRND")) {
4662             return true;
4663         }
4664         if (!strcmp(var, "$DIMSAH")) {
4665             return true;
4666         }
4667         if (!strcmp(var, "$DIMSCALE")) {
4668             return true;
4669         }
4670         if (!strcmp(var, "$DIMSE1")) {
4671             return true;
4672         }
4673         if (!strcmp(var, "$DIMSE2")) {
4674             return true;
4675         }
4676         if (!strcmp(var, "$DIMSHO")) {
4677             return true;
4678         }
4679         if (!strcmp(var, "$DIMSOXD")) {
4680             return true;
4681         }
4682         if (!strcmp(var, "$DIMSTYLE")) {
4683             return true;
4684         }
4685         if (!strcmp(var, "$DIMTAD")) {
4686             return true;
4687         }
4688         if (!strcmp(var, "$DIMTFAC")) {
4689             return true;
4690         }
4691         if (!strcmp(var, "$DIMTIH")) {
4692             return true;
4693         }
4694         if (!strcmp(var, "$DIMTIX")) {
4695             return true;
4696         }
4697         if (!strcmp(var, "$DIMTM")) {
4698             return true;
4699         }
4700         if (!strcmp(var, "$DIMTOFL")) {
4701             return true;
4702         }
4703         if (!strcmp(var, "$DIMTOH")) {
4704             return true;
4705         }
4706         if (!strcmp(var, "$DIMTOL")) {
4707             return true;
4708         }
4709         if (!strcmp(var, "$DIMTP")) {
4710             return true;
4711         }
4712         if (!strcmp(var, "$DIMTSZ")) {
4713             return true;
4714         }
4715         if (!strcmp(var, "$DIMTVP")) {
4716             return true;
4717         }
4718         if (!strcmp(var, "$DIMTXT")) {
4719             return true;
4720         }
4721         if (!strcmp(var, "$DIMZIN")) {
4722             return true;
4723         }
4724         if (!strcmp(var, "$DWGCODEPAGE")) {
4725             return true;
4726         }
4727         if (!strcmp(var, "$DRAGMODE")) {
4728             return true;
4729         }
4730         if (!strcmp(var, "$ELEVATION")) {
4731             return true;
4732         }
4733         if (!strcmp(var, "$EXTMAX")) {
4734             return true;
4735         }
4736         if (!strcmp(var, "$EXTMIN")) {
4737             return true;
4738         }
4739         if (!strcmp(var, "$FILLETRAD")) {
4740             return true;
4741         }
4742         if (!strcmp(var, "$FILLMODE")) {
4743             return true;
4744         }
4745         if (!strcmp(var, "$HANDLING")) {
4746             return true;
4747         }
4748         if (!strcmp(var, "$HANDSEED")) {
4749             return true;
4750         }
4751         if (!strcmp(var, "$INSBASE")) {
4752             return true;
4753         }
4754         if (!strcmp(var, "$LIMCHECK")) {
4755             return true;
4756         }
4757         if (!strcmp(var, "$LIMMAX")) {
4758             return true;
4759         }
4760         if (!strcmp(var, "$LIMMIN")) {
4761             return true;
4762         }
4763         if (!strcmp(var, "$LTSCALE")) {
4764             return true;
4765         }
4766         if (!strcmp(var, "$LUNITS")) {
4767             return true;
4768         }
4769         if (!strcmp(var, "$LUPREC")) {
4770             return true;
4771         }
4772         if (!strcmp(var, "$MAXACTVP")) {
4773             return true;
4774         }
4775         if (!strcmp(var, "$MENU")) {
4776             return true;
4777         }
4778         if (!strcmp(var, "$MIRRTEXT")) {
4779             return true;
4780         }
4781         if (!strcmp(var, "$ORTHOMODE")) {
4782             return true;
4783         }
4784         if (!strcmp(var, "$OSMODE")) {
4785             return true;
4786         }
4787         if (!strcmp(var, "$PDMODE")) {
4788             return true;
4789         }
4790         if (!strcmp(var, "$PDSIZE")) {
4791             return true;
4792         }
4793         if (!strcmp(var, "$PELEVATION")) {
4794             return true;
4795         }
4796         if (!strcmp(var, "$PEXTMAX")) {
4797             return true;
4798         }
4799         if (!strcmp(var, "$PEXTMIN")) {
4800             return true;
4801         }
4802         if (!strcmp(var, "$PLIMCHECK")) {
4803             return true;
4804         }
4805         if (!strcmp(var, "$PLIMMAX")) {
4806             return true;
4807         }
4808         if (!strcmp(var, "$PLIMMIN")) {
4809             return true;
4810         }
4811         if (!strcmp(var, "$PLINEGEN")) {
4812             return true;
4813         }
4814         if (!strcmp(var, "$PLINEWID")) {
4815             return true;
4816         }
4817         if (!strcmp(var, "$PSLTSCALE")) {
4818             return true;
4819         }
4820         if (!strcmp(var, "$PUCSNAME")) {
4821             return true;
4822         }
4823         if (!strcmp(var, "$PUCSORG")) {
4824             return true;
4825         }
4826         if (!strcmp(var, "$PUCSXDIR")) {
4827             return true;
4828         }
4829         if (!strcmp(var, "$PUCSYDIR")) {
4830             return true;
4831         }
4832         if (!strcmp(var, "$QTEXTMODE")) {
4833             return true;
4834         }
4835         if (!strcmp(var, "$REGENMODE")) {
4836             return true;
4837         }
4838         if (!strcmp(var, "$SHADEDGE")) {
4839             return true;
4840         }
4841         if (!strcmp(var, "$SHADEDIF")) {
4842             return true;
4843         }
4844         if (!strcmp(var, "$SKETCHINC")) {
4845             return true;
4846         }
4847         if (!strcmp(var, "$SKPOLY")) {
4848             return true;
4849         }
4850         if (!strcmp(var, "$SPLFRAME")) {
4851             return true;
4852         }
4853         if (!strcmp(var, "$SPLINESEGS")) {
4854             return true;
4855         }
4856         if (!strcmp(var, "$SPLINETYPE")) {
4857             return true;
4858         }
4859         if (!strcmp(var, "$SURFTAB1")) {
4860             return true;
4861         }
4862         if (!strcmp(var, "$SURFTAB2")) {
4863             return true;
4864         }
4865         if (!strcmp(var, "$SURFTYPE")) {
4866             return true;
4867         }
4868         if (!strcmp(var, "$SURFU")) {
4869             return true;
4870         }
4871         if (!strcmp(var, "$SURFV")) {
4872             return true;
4873         }
4874         if (!strcmp(var, "$TDCREATE")) {
4875             return true;
4876         }
4877         if (!strcmp(var, "$TDINDWG")) {
4878             return true;
4879         }
4880         if (!strcmp(var, "$TDUPDATE")) {
4881             return true;
4882         }
4883         if (!strcmp(var, "$TDUSRTIMER")) {
4884             return true;
4885         }
4886         if (!strcmp(var, "$TEXTSIZE")) {
4887             return true;
4888         }
4889         if (!strcmp(var, "$TEXTSTYLE")) {
4890             return true;
4891         }
4892         if (!strcmp(var, "$THICKNESS")) {
4893             return true;
4894         }
4895         if (!strcmp(var, "$TILEMODE")) {
4896             return true;
4897         }
4898         if (!strcmp(var, "$TRACEWID")) {
4899             return true;
4900         }
4901         if (!strcmp(var, "$UCSNAME")) {
4902             return true;
4903         }
4904         if (!strcmp(var, "$UCSORG")) {
4905             return true;
4906         }
4907         if (!strcmp(var, "$UCSXDIR")) {
4908             return true;
4909         }
4910         if (!strcmp(var, "$UCSYDIR")) {
4911             return true;
4912         }
4913         if (!strcmp(var, "$UNITMODE")) {
4914             return true;
4915         }
4916         if (!strcmp(var, "$USERI1")) {
4917             return true;
4918         }
4919         if (!strcmp(var, "$USERR1")) {
4920             return true;
4921         }
4922         if (!strcmp(var, "$USRTIMER")) {
4923             return true;
4924         }
4925         if (!strcmp(var, "$VISRETAIN")) {
4926             return true;
4927         }
4928         if (!strcmp(var, "$WORLDVIEW")) {
4929             return true;
4930         }
4931         if (!strcmp(var, "$FASTZOOM")) {
4932             return true;
4933         }
4934         if (!strcmp(var, "$GRIDMODE")) {
4935             return true;
4936         }
4937         if (!strcmp(var, "$GRIDUNIT")) {
4938             return true;
4939         }
4940         if (!strcmp(var, "$SNAPANG")) {
4941             return true;
4942         }
4943         if (!strcmp(var, "$SNAPBASE")) {
4944             return true;
4945         }
4946         if (!strcmp(var, "$SNAPISOPAIR")) {
4947             return true;
4948         }
4949         if (!strcmp(var, "$SNAPMODE")) {
4950             return true;
4951         }
4952         if (!strcmp(var, "$SNAPSTYLE")) {
4953             return true;
4954         }
4955         if (!strcmp(var, "$SNAPUNIT")) {
4956             return true;
4957         }
4958         if (!strcmp(var, "$VIEWCTR")) {
4959             return true;
4960         }
4961         if (!strcmp(var, "$VIEWDIR")) {
4962             return true;
4963         }
4964         if (!strcmp(var, "$VIEWSIZE")) {
4965             return true;
4966         }
4967         return false;
4968     }
4969 
4970     return false;
4971 }
4972 
4973 
4974 
4975 /**
4976  * @returns the library version as int (4 bytes, each byte one version number).
4977  * e.g. if str = "2.0.2.0" getLibVersion returns 0x02000200
4978  */
getLibVersion(const char * str)4979 int DL_Dxf::getLibVersion(const char* str) {
4980     int d[4];
4981     int idx = 0;
4982     char v[4][5];
4983     int ret = 0;
4984 
4985     for (unsigned int i=0; i<strlen(str) && idx<3; ++i) {
4986         if (str[i]=='.') {
4987             d[idx] = i;
4988             idx++;
4989         }
4990     }
4991 
4992     if (idx==3) {
4993         d[3] = strlen(str);
4994 
4995         strncpy(v[0], str, d[0]);
4996         v[0][d[0]] = '\0';
4997 
4998         strncpy(v[1], &str[d[0]+1], d[1]-d[0]-1);
4999         v[1][d[1]-d[0]-1] = '\0';
5000 
5001         strncpy(v[2], &str[d[1]+1], d[2]-d[1]-1);
5002         v[2][d[2]-d[1]-1] = '\0';
5003 
5004         strncpy(v[3], &str[d[2]+1], d[3]-d[2]-1);
5005         v[3][d[3]-d[2]-1] = '\0';
5006 
5007         ret = (atoi(v[0])<<(3*8)) +
5008               (atoi(v[1])<<(2*8)) +
5009               (atoi(v[2])<<(1*8)) +
5010               (atoi(v[3])<<(0*8));
5011 
5012         return ret;
5013     } else {
5014         std::cerr << "DL_Dxf::getLibVersion: invalid version number: " << str << "\n";
5015         return 0;
5016     }
5017 }
5018 
5019 
5020 
5021 /**
5022  * Some test routines.
5023  */
test()5024 void DL_Dxf::test() {
5025     char* buf1;
5026     char* buf2;
5027     char* buf3;
5028     char* buf4;
5029     char* buf5;
5030     char* buf6;
5031 
5032     buf1 = new char[10];
5033     buf2 = new char[10];
5034     buf3 = new char[10];
5035     buf4 = new char[10];
5036     buf5 = new char[10];
5037     buf6 = new char[10];
5038 
5039     strcpy(buf1, "  10\n");
5040     strcpy(buf2, "10");
5041     strcpy(buf3, "10\n");
5042     strcpy(buf4, "  10 \n");
5043     strcpy(buf5, "  10 \r");
5044     strcpy(buf6, "\t10 \n");
5045 
5046     std::cout << "1 buf1: '" << buf1 << "'\n";
5047     stripWhiteSpace(&buf1);
5048     std::cout << "2 buf1: '" << buf1 << "'\n";
5049     //assert(!strcmp(buf1, "10"));
5050 
5051     std::cout << "1 buf2: '" << buf2 << "'\n";
5052     stripWhiteSpace(&buf2);
5053     std::cout << "2 buf2: '" << buf2 << "'\n";
5054 
5055     std::cout << "1 buf3: '" << buf3 << "'\n";
5056     stripWhiteSpace(&buf3);
5057     std::cout << "2 buf3: '" << buf3 << "'\n";
5058 
5059     std::cout << "1 buf4: '" << buf4 << "'\n";
5060     stripWhiteSpace(&buf4);
5061     std::cout << "2 buf4: '" << buf4 << "'\n";
5062 
5063     std::cout << "1 buf5: '" << buf5 << "'\n";
5064     stripWhiteSpace(&buf5);
5065     std::cout << "2 buf5: '" << buf5 << "'\n";
5066 
5067     std::cout << "1 buf6: '" << buf6 << "'\n";
5068     stripWhiteSpace(&buf6);
5069     std::cout << "2 buf6: '" << buf6 << "'\n";
5070 
5071 }
5072 
5073 
5074