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