3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_filterdxf.h"
19 #include "dl_attributes.h"
21 #include "dl_writer_ascii.h"
22 #include "rs_dimaligned.h"
23 #include "rs_dimangular.h"
24 #include "rs_dimdiametric.h"
25 #include "rs_dimlinear.h"
26 #include "rs_dimradial.h"
29 #include "rs_leader.h"
30 #include "rs_system.h"
33 * Default constructor.
36 RS_FilterDXF::RS_FilterDXF(): RS_FilterInterface()
38 RS_DEBUG->print("RS_FilterDXF::RS_FilterDXF()");
40 addImportFormat(RS2::FormatDXF);
41 addExportFormat(RS2::FormatDXF);
42 addExportFormat(RS2::FormatDXF12);
49 currentContainer = NULL;
51 //exportVersion = DL_Codes::VER_2002;
52 //systemVariables.setAutoDelete(true);
53 RS_DEBUG->print("RS_FilterDXF::RS_FilterDXF(): OK");
59 RS_FilterDXF::~RS_FilterDXF()
61 RS_DEBUG->print("RS_FilterDXF::~RS_FilterDXF()");
62 RS_DEBUG->print("RS_FilterDXF::~RS_FilterDXF(): OK");
66 * Implementation of the method used for RS_Import to communicate
69 * @param g The graphic in which the entities from the file
70 * will be created or the graphics from which the entities are
71 * taken to be stored in a file.
73 bool RS_FilterDXF::fileImport(RS_Graphic & g, const QString & file, RS2::FormatType /*type*/)
75 RS_DEBUG->print("RS_FilterDXF::fileImport");
76 //RS_DEBUG->timestamp();
78 RS_DEBUG->print("DXF Filter: importing file '%s'...", (const char *)QFile::encodeName(file));
81 currentContainer = graphic;
84 RS_DEBUG->print("graphic->countLayers(): %d", graphic->countLayers());
86 //graphic->setAutoUpdateBorders(false);
87 RS_DEBUG->print("RS_FilterDXF::fileImport: reading file");
88 bool success = dxf.in((const char *)QFile::encodeName(file), this);
89 RS_DEBUG->print("RS_FilterDXF::fileImport: reading file: OK");
90 //graphic->setAutoUpdateBorders(true);
94 RS_DEBUG->print(RS_Debug::D_WARNING, "Cannot open DXF file '%s'.",
95 (const char *)QFile::encodeName(file));
99 RS_DEBUG->print("RS_FilterDXF::fileImport: adding variables");
101 // add some variables that need to be there for DXF drawings:
102 if (graphic->getVariableString("$DIMSTYLE", "").isEmpty())
104 RS_DEBUG->print("RS_FilterDXF::fileImport: adding DIMSTYLE");
105 graphic->addVariable("$DIMSTYLE", "Standard", 2);
106 RS_DEBUG->print("RS_FilterDXF::fileImport: adding DIMSTYLE: OK");
109 RS_DEBUG->print("RS_FilterDXF::fileImport: adding variables: OK");
111 RS_DEBUG->print("RS_FilterDXF::fileImport: updating inserts");
112 graphic->updateInserts();
113 RS_DEBUG->print("RS_FilterDXF::fileImport: updating inserts: OK");
115 RS_DEBUG->print("RS_FilterDXF::fileImport OK");
116 //RS_DEBUG->timestamp();
122 * Implementation of the method which handles layers.
124 void RS_FilterDXF::addLayer(const DL_LayerData& data) {
125 RS_DEBUG->print("RS_FilterDXF::addLayer");
126 RS_DEBUG->print(" adding layer: %s", data.name.c_str());
128 RS_DEBUG->print("RS_FilterDXF::addLayer: creating layer");
129 RS_Layer* layer = new RS_Layer(data.name.c_str());
130 RS_DEBUG->print("RS_FilterDXF::addLayer: set pen");
131 layer->setPen(attributesToPen(attributes));
132 //layer->setFlags(data.flags&0x07);
134 RS_DEBUG->print("RS_FilterDXF::addLayer: flags");
135 if (data.flags&0x01) {
138 if (data.flags&0x04) {
142 RS_DEBUG->print("RS_FilterDXF::addLayer: add layer to graphic");
143 graphic->addLayer(layer);
144 RS_DEBUG->print("RS_FilterDXF::addLayer: OK");
148 * Implementation of the method which handles blocks.
150 * @todo Adding blocks to blocks (stack for currentContainer)
152 void RS_FilterDXF::addBlock(const DL_BlockData & data)
154 RS_DEBUG->print("RS_FilterDXF::addBlock");
155 RS_DEBUG->print(" adding block: %s", data.name.c_str());
157 // Prevent special blocks (paper_space, model_space) from being added:
158 if (QString(data.name.c_str()).toLower() != "*paper_space0"
159 && QString(data.name.c_str()).toLower() != "*paper_space"
160 && QString(data.name.c_str()).toLower() != "*model_space"
161 && QString(data.name.c_str()).toLower() != "$paper_space0"
162 && QString(data.name.c_str()).toLower() != "$paper_space"
163 && QString(data.name.c_str()).toLower() != "$model_space")
166 #ifndef RS_NO_COMPLEX_ENTITIES
167 if (QString(data.name.c_str()).startsWith("__CE"))
169 RS_EntityContainer * ec = new RS_EntityContainer();
171 currentContainer = ec;
172 graphic->addEntity(ec);
173 //currentContainer->setLayer(graphic->findLayer("0"));
178 Vector bp(data.bpx, data.bpy);
179 RS_Block * block = new RS_Block(graphic, RS_BlockData(data.name.c_str(), bp, false));
180 //block->setFlags(flags);
182 if (graphic->addBlock(block))
183 currentContainer = block;
184 #ifndef RS_NO_COMPLEX_ENTITIES
191 * Implementation of the method which closes blocks.
193 void RS_FilterDXF::endBlock()
195 currentContainer = graphic;
199 * Implementation of the method which handles point entities.
201 void RS_FilterDXF::addPoint(const DL_PointData & data)
203 Vector v(data.x, data.y);
204 RS_Point * entity = new RS_Point(currentContainer, RS_PointData(v));
205 setEntityAttributes(entity, attributes);
206 currentContainer->addEntity(entity);
210 * Implementation of the method which handles line entities.
212 void RS_FilterDXF::addLine(const DL_LineData & data)
214 RS_DEBUG->print("RS_FilterDXF::addLine");
216 Vector v1(data.x1, data.y1);
217 Vector v2(data.x2, data.y2);
219 RS_DEBUG->print("RS_FilterDXF::addLine: create line");
221 if (currentContainer == NULL)
222 RS_DEBUG->print("RS_FilterDXF::addLine: currentContainer is NULL");
224 RS_Line * entity = new RS_Line(currentContainer, RS_LineData(v1, v2));
225 RS_DEBUG->print("RS_FilterDXF::addLine: set attributes");
226 setEntityAttributes(entity, attributes);
228 RS_DEBUG->print("RS_FilterDXF::addLine: add entity");
230 currentContainer->addEntity(entity);
232 RS_DEBUG->print("RS_FilterDXF::addLine: OK");
236 * Implementation of the method which handles arc entities.
238 * @param angle1 Start angle in deg (!)
239 * @param angle2 End angle in deg (!)
241 void RS_FilterDXF::addArc(const DL_ArcData& data) {
242 RS_DEBUG->print("RS_FilterDXF::addArc");
243 //printf("LINE (%12.6f, %12.6f, %12.6f) (%12.6f, %12.6f, %12.6f)\n",
244 // p1[0], p1[1], p1[2],
245 // p2[0], p2[1], p2[2]);
246 Vector v(data.cx, data.cy);
247 RS_ArcData d(v, data.radius,
251 RS_Arc* entity = new RS_Arc(currentContainer, d);
252 setEntityAttributes(entity, attributes);
254 currentContainer->addEntity(entity);
260 * Implementation of the method which handles ellipse entities.
262 * @param angle1 Start angle in rad (!)
263 * @param angle2 End angle in rad (!)
265 void RS_FilterDXF::addEllipse(const DL_EllipseData& data) {
266 RS_DEBUG->print("RS_FilterDXF::addEllipse");
268 Vector v1(data.cx, data.cy);
269 Vector v2(data.mx, data.my);
271 RS_EllipseData ed(v1, v2,
276 RS_Ellipse* entity = new RS_Ellipse(currentContainer, ed);
277 setEntityAttributes(entity, attributes);
279 currentContainer->addEntity(entity);
285 * Implementation of the method which handles circle entities.
287 void RS_FilterDXF::addCircle(const DL_CircleData& data) {
288 RS_DEBUG->print("RS_FilterDXF::addCircle");
289 //printf("LINE (%12.6f, %12.6f, %12.6f) (%12.6f, %12.6f, %12.6f)\n",
290 // p1[0], p1[1], p1[2],
291 // p2[0], p2[1], p2[2]);
293 Vector v(data.cx, data.cy);
294 RS_CircleData d(v, data.radius);
295 RS_Circle* entity = new RS_Circle(currentContainer, d);
296 setEntityAttributes(entity, attributes);
298 currentContainer->addEntity(entity);
304 * Implementation of the method which handles polyline entities.
306 void RS_FilterDXF::addPolyline(const DL_PolylineData& data) {
307 RS_DEBUG->print("RS_FilterDXF::addPolyline");
308 //RS_DEBUG->print("RS_FilterDXF::addPolyline()");
309 RS_PolylineData d(Vector(false),
312 polyline = new RS_Polyline(currentContainer, d);
313 setEntityAttributes(polyline, attributes);
315 currentContainer->addEntity(polyline);
321 * Implementation of the method which handles polyline vertices.
323 void RS_FilterDXF::addVertex(const DL_VertexData& data) {
324 RS_DEBUG->print("RS_FilterDXF::addVertex(): %f/%f bulge: %f",
325 data.x, data.y, data.bulge);
327 Vector v(data.x, data.y);
329 if (polyline!=NULL) {
330 polyline->addVertex(v, data.bulge);
337 * Implementation of the method which handles splines.
339 void RS_FilterDXF::addSpline(const DL_SplineData& data) {
340 RS_DEBUG->print("RS_FilterDXF::addSpline: degree: %d", data.degree);
342 if (data.degree>=1 && data.degree<=3) {
343 RS_SplineData d(data.degree, ((data.flags&0x1)==0x1));
344 spline = new RS_Spline(currentContainer, d);
345 setEntityAttributes(spline, attributes);
347 currentContainer->addEntity(spline);
349 RS_DEBUG->print(RS_Debug::D_WARNING,
350 "RS_FilterDXF::addSpline: Invalid degree for spline: %d. "
351 "Accepted values are 1..3.", data.degree);
355 /*virtual*/ void RS_FilterDXF::addKnot(const DL_KnotData &)
360 * Implementation of the method which handles spline control points.
362 void RS_FilterDXF::addControlPoint(const DL_ControlPointData & data)
364 RS_DEBUG->print("RS_FilterDXF::addControlPoint: %f/%f", data.x, data.y);
366 Vector v(data.x, data.y);
370 spline->addControlPoint(v);
376 * Implementation of the method which handles inserts.
378 void RS_FilterDXF::addInsert(const DL_InsertData & data)
380 RS_DEBUG->print("RS_FilterDXF::addInsert");
382 if (QString(data.name.c_str()).left(3) == "A$C")
385 Vector ip(data.ipx, data.ipy);
386 Vector sc(data.sx, data.sy);
387 Vector sp(data.colSp, data.rowSp);
389 //cout << "Insert: " << name << " " << ip << " " << cols << "/" << rows << endl;
391 RS_InsertData d(data.name.c_str(), ip, sc, data.angle / ARAD, data.cols, data.rows,
392 sp, NULL, RS2::NoUpdate);
393 RS_Insert * entity = new RS_Insert(currentContainer, d);
394 setEntityAttributes(entity, attributes);
395 RS_DEBUG->print(" id: %d", entity->getId());
397 currentContainer->addEntity(entity);
400 /*virtual*/ void RS_FilterDXF::addTrace(const DL_TraceData &)
404 /*virtual*/ void RS_FilterDXF::addSolid(const DL_SolidData &)
409 * Implementation of the method which handles text
410 * chunks for MText entities.
412 void RS_FilterDXF::addMTextChunk(const char * text)
414 RS_DEBUG->print("RS_FilterDXF::addMTextChunk: %s", text);
416 //mtext += QString::fromUtf8(text);
419 QCString locallyEncoded = text;
420 QString enc = RS_System::getEncoding(variables.getString("$DWGCODEPAGE", "ANSI_1252"));
421 QTextCodec *codec = QTextCodec::codecForName(enc); // get the codec for Japanese
423 mtext += codec->toUnicode(toNativeString(locallyEncoded));
425 mtext += toNativeString(text);
432 * Implementation of the method which handles
433 * multi texts (MTEXT).
435 void RS_FilterDXF::addMText(const DL_MTextData & data)
437 RS_DEBUG->print("RS_FilterDXF::addMText: %s", data.text.c_str());
439 Vector ip(data.ipx, data.ipy);
442 RS2::TextDrawingDirection dir;
443 RS2::TextLineSpacingStyle lss;
444 QString sty = data.style.c_str();
446 if (data.attachmentPoint <= 3)
447 valign = RS2::VAlignTop;
448 else if (data.attachmentPoint <= 6)
449 valign = RS2::VAlignMiddle;
451 valign = RS2::VAlignBottom;
453 if (data.attachmentPoint % 3 == 1)
454 halign = RS2::HAlignLeft;
455 else if (data.attachmentPoint % 3 == 2)
456 halign = RS2::HAlignCenter;
458 halign = RS2::HAlignRight;
460 if (data.drawingDirection == 1)
461 dir = RS2::LeftToRight;
462 else if (data.drawingDirection == 3)
463 dir = RS2::TopToBottom;
467 if (data.lineSpacingStyle == 1)
472 mtext += QString(data.text.c_str());
474 QString locallyEncoded = mtext;
475 QString enc = RS_System::getEncoding(variables.getString("$DWGCODEPAGE", "ANSI_1252"));
476 // get the codec for Japanese
477 QTextCodec * codec = QTextCodec::codecForName(enc.toAscii());
480 mtext = codec->toUnicode(toNativeString(locallyEncoded).toAscii());
482 mtext = toNativeString(mtext);
484 // use default style for the drawing:
487 // japanese, cyrillic:
488 QString codepage = variables.getString("$DWGCODEPAGE", "ANSI_1252");
490 if (codepage == "ANSI_932" || codepage == "ANSI_1251")
493 sty = variables.getString("$TEXTSTYLE", "Standard");
496 RS_DEBUG->print("Text as unicode:");
497 RS_DEBUG->printUnicode(mtext);
499 RS_TextData d(ip, data.height, data.width, valign, halign, dir, lss,
500 data.lineSpacingFactor, mtext, sty, data.angle, RS2::NoUpdate);
501 RS_Text * entity = new RS_Text(currentContainer, d);
503 setEntityAttributes(entity, attributes);
505 currentContainer->addEntity(entity);
513 * Implementation of the method which handles
516 void RS_FilterDXF::addText(const DL_TextData& data) {
517 RS_DEBUG->print("RS_FilterDXF::addText");
520 double angle = data.angle;
522 // TODO: check, maybe implement a separate TEXT instead of using MTEXT
524 // baseline has 5 vertical alignment modes:
525 if (data.vJustification!=0 || data.hJustification!=0) {
526 switch (data.hJustification) {
528 case 0: // left aligned
530 refPoint = Vector(data.apx, data.apy);
534 refPoint = Vector(data.apx, data.apy);
536 case 2: // right aligned
538 refPoint = Vector(data.apx, data.apy);
540 case 3: // aligned (TODO)
542 refPoint = Vector((data.ipx+data.apx)/2.0,
543 (data.ipy+data.apy)/2.0);
545 Vector(data.ipx, data.ipy).angleTo(
546 Vector(data.apx, data.apy));
548 case 4: // Middle (TODO)
550 refPoint = Vector(data.apx, data.apy);
552 case 5: // fit (TODO)
554 refPoint = Vector((data.ipx+data.apx)/2.0,
555 (data.ipy+data.apy)/2.0);
557 Vector(data.ipx, data.ipy).angleTo(
558 Vector(data.apx, data.apy));
562 switch (data.vJustification) {
566 attachmentPoint += 6;
570 attachmentPoint += 3;
577 //attachmentPoint = (data.hJustification+1)+(3-data.vJustification)*3;
579 refPoint = Vector(data.ipx, data.ipy);
582 int drawingDirection = 5;
583 double width = 100.0;
586 addMText(DL_MTextData(
595 data.text.c_str(), data.style,
602 * Implementation of the method which handles
603 * dimensions (DIMENSION).
605 RS_DimensionData RS_FilterDXF::convDimensionData(
606 const DL_DimensionData& data) {
608 Vector defP(data.dpx, data.dpy);
609 Vector midP(data.mpx, data.mpy);
612 RS2::TextLineSpacingStyle lss;
613 QString sty = data.style.c_str();
614 QString t; //= data.text;
616 // middlepoint of text can be 0/0 which is considered to be invalid (!):
617 // 0/0 because older QCad versions save the middle of the text as 0/0
618 // althought they didn't suport saving of the middle of the text.
619 if (fabs(data.mpx)<1.0e-6 && fabs(data.mpy)<1.0e-6) {
620 midP = Vector(false);
623 if (data.attachmentPoint<=3) {
624 valign=RS2::VAlignTop;
625 } else if (data.attachmentPoint<=6) {
626 valign=RS2::VAlignMiddle;
628 valign=RS2::VAlignBottom;
631 if (data.attachmentPoint%3==1) {
632 halign=RS2::HAlignLeft;
633 } else if (data.attachmentPoint%3==2) {
634 halign=RS2::HAlignCenter;
636 halign=RS2::HAlignRight;
639 if (data.lineSpacingStyle==1) {
645 t = toNativeString(data.text.c_str());
648 sty = variables.getString("$DIMSTYLE", "Standard");
651 RS_DEBUG->print("Text as unicode:");
652 RS_DEBUG->printUnicode(t);
654 // data needed to add the actual dimension entity
655 return RS_DimensionData(defP, midP,
658 data.lineSpacingFactor,
665 * Implementation of the method which handles
666 * aligned dimensions (DIMENSION).
668 void RS_FilterDXF::addDimAlign(const DL_DimensionData& data,
669 const DL_DimAlignedData& edata) {
670 RS_DEBUG->print("RS_FilterDXF::addDimAligned");
672 RS_DimensionData dimensionData = convDimensionData(data);
674 Vector ext1(edata.epx1, edata.epy1);
675 Vector ext2(edata.epx2, edata.epy2);
677 RS_DimAlignedData d(ext1, ext2);
679 RS_DimAligned* entity = new RS_DimAligned(currentContainer,
681 setEntityAttributes(entity, attributes);
683 currentContainer->addEntity(entity);
689 * Implementation of the method which handles
690 * linear dimensions (DIMENSION).
692 void RS_FilterDXF::addDimLinear(const DL_DimensionData& data,
693 const DL_DimLinearData& edata) {
694 RS_DEBUG->print("RS_FilterDXF::addDimLinear");
696 RS_DimensionData dimensionData = convDimensionData(data);
698 Vector dxt1(edata.dpx1, edata.dpy1);
699 Vector dxt2(edata.dpx2, edata.dpy2);
701 RS_DimLinearData d(dxt1, dxt2, RS_Math::deg2rad(edata.angle),
702 RS_Math::deg2rad(edata.oblique));
704 RS_DimLinear* entity = new RS_DimLinear(currentContainer,
706 setEntityAttributes(entity, attributes);
708 currentContainer->addEntity(entity);
714 * Implementation of the method which handles
715 * radial dimensions (DIMENSION).
717 void RS_FilterDXF::addDimRadial(const DL_DimensionData& data,
718 const DL_DimRadialData& edata) {
719 RS_DEBUG->print("RS_FilterDXF::addDimRadial");
721 RS_DimensionData dimensionData = convDimensionData(data);
722 Vector dp(edata.dpx, edata.dpy);
724 RS_DimRadialData d(dp, edata.leader);
726 RS_DimRadial* entity = new RS_DimRadial(currentContainer,
729 setEntityAttributes(entity, attributes);
731 currentContainer->addEntity(entity);
737 * Implementation of the method which handles
738 * diametric dimensions (DIMENSION).
740 void RS_FilterDXF::addDimDiametric(const DL_DimensionData& data,
741 const DL_DimDiametricData& edata) {
742 RS_DEBUG->print("RS_FilterDXF::addDimDiametric");
744 RS_DimensionData dimensionData = convDimensionData(data);
745 Vector dp(edata.dpx, edata.dpy);
747 RS_DimDiametricData d(dp, edata.leader);
749 RS_DimDiametric* entity = new RS_DimDiametric(currentContainer,
752 setEntityAttributes(entity, attributes);
754 currentContainer->addEntity(entity);
760 * Implementation of the method which handles
761 * angular dimensions (DIMENSION).
763 void RS_FilterDXF::addDimAngular(const DL_DimensionData& data,
764 const DL_DimAngularData& edata) {
765 RS_DEBUG->print("RS_FilterDXF::addDimAngular");
767 RS_DimensionData dimensionData = convDimensionData(data);
768 Vector dp1(edata.dpx1, edata.dpy1);
769 Vector dp2(edata.dpx2, edata.dpy2);
770 Vector dp3(edata.dpx3, edata.dpy3);
771 Vector dp4(edata.dpx4, edata.dpy4);
773 RS_DimAngularData d(dp1, dp2, dp3, dp4);
775 RS_DimAngular* entity = new RS_DimAngular(currentContainer,
778 setEntityAttributes(entity, attributes);
780 currentContainer->addEntity(entity);
786 * Implementation of the method which handles
787 * angular dimensions (DIMENSION).
789 void RS_FilterDXF::addDimAngular3P(const DL_DimensionData& data,
790 const DL_DimAngular3PData& edata) {
791 RS_DEBUG->print("RS_FilterDXF::addDimAngular3P");
793 RS_DimensionData dimensionData = convDimensionData(data);
794 Vector dp1(edata.dpx3, edata.dpy3);
795 Vector dp2(edata.dpx1, edata.dpy1);
796 Vector dp3(edata.dpx3, edata.dpy3);
797 Vector dp4 = dimensionData.definitionPoint;
798 dimensionData.definitionPoint = Vector(edata.dpx2, edata.dpy2);
800 RS_DimAngularData d(dp1, dp2, dp3, dp4);
802 RS_DimAngular* entity = new RS_DimAngular(currentContainer,
805 setEntityAttributes(entity, attributes);
807 currentContainer->addEntity(entity);
813 * Implementation of the method which handles leader entities.
815 void RS_FilterDXF::addLeader(const DL_LeaderData& data) {
816 RS_DEBUG->print("RS_FilterDXF::addDimLeader");
817 //RS_DEBUG->print("RS_FilterDXF::addPolyline()");
818 RS_LeaderData d(data.arrowHeadFlag==1);
819 leader = new RS_Leader(currentContainer, d);
820 setEntityAttributes(leader, attributes);
822 currentContainer->addEntity(leader);
828 * Implementation of the method which handles leader vertices.
830 void RS_FilterDXF::addLeaderVertex(const DL_LeaderVertexData& data) {
831 RS_DEBUG->print("RS_FilterDXF::addLeaderVertex");
832 //RS_DEBUG->print("RS_FilterDXF::addVertex() bulge: %f", bulge);
834 Vector v(data.x, data.y);
837 leader->addVertex(v);
844 * Implementation of the method which handles hatch entities.
846 void RS_FilterDXF::addHatch(const DL_HatchData& data) {
847 RS_DEBUG->print("RS_FilterDXF::addHatch()");
849 hatch = new RS_Hatch(currentContainer,
850 RS_HatchData(data.solid,
853 QString(data.pattern.c_str())));
854 setEntityAttributes(hatch, attributes);
856 currentContainer->addEntity(hatch);
862 * Implementation of the method which handles hatch loops.
864 void RS_FilterDXF::addHatchLoop(const DL_HatchLoopData& /*data*/) {
865 RS_DEBUG->print("RS_FilterDXF::addHatchLoop()");
867 hatchLoop = new RS_EntityContainer(hatch);
868 hatchLoop->setLayer(NULL);
869 hatch->addEntity(hatchLoop);
876 * Implementation of the method which handles hatch edge entities.
878 void RS_FilterDXF::addHatchEdge(const DL_HatchEdgeData& data) {
879 RS_DEBUG->print("RS_FilterDXF::addHatchEdge()");
881 if (hatchLoop!=NULL) {
885 RS_DEBUG->print("RS_FilterDXF::addHatchEdge(): "
887 data.x1, data.y1, data.x2, data.y2);
888 e = new RS_Line(hatchLoop,
889 RS_LineData(Vector(data.x1, data.y1),
890 Vector(data.x2, data.y2)));
893 if (data.ccw && data.angle1<1.0e-6 && data.angle2>2*M_PI-1.0e-6) {
894 e = new RS_Circle(hatchLoop,
895 RS_CircleData(Vector(data.cx, data.cy),
901 RS_ArcData(Vector(data.cx, data.cy),
903 RS_Math::correctAngle(data.angle1),
904 RS_Math::correctAngle(data.angle2),
909 RS_ArcData(Vector(data.cx, data.cy),
911 RS_Math::correctAngle(2*M_PI-data.angle1),
912 RS_Math::correctAngle(2*M_PI-data.angle2),
923 hatchLoop->addEntity(e);
931 * Implementation of the method which handles image entities.
933 void RS_FilterDXF::addImage(const DL_ImageData& data) {
934 RS_DEBUG->print("RS_FilterDXF::addImage");
936 Vector ip(data.ipx, data.ipy);
937 Vector uv(data.ux, data.uy);
938 Vector vv(data.vx, data.vy);
939 Vector size(data.width, data.height);
944 RS_ImageData(QString(data.ref.c_str()).toInt(NULL, 16),
952 setEntityAttributes(image, attributes);
953 currentContainer->addEntity(image);
957 * Implementation of the method which links image entities to image files.
959 void RS_FilterDXF::linkImage(const DL_ImageDefData & data)
961 RS_DEBUG->print("RS_FilterDXF::linkImage");
963 int handle = QString(data.ref.c_str()).toInt(NULL, 16);
964 QString sfile(data.file.c_str());
965 QFileInfo fiDxf(file);
966 QFileInfo fiBitmap(sfile);
968 // try to find the image file:
970 // first: absolute path:
971 if (!fiBitmap.exists())
973 RS_DEBUG->print("File %s doesn't exist.", (const char *)QFile::encodeName(sfile));
974 // try relative path:
975 // QString f1 = fiDxf.dirPath(true) + "/" + sfile;
976 QString f1 = fiDxf.absolutePath() + "/" + sfile;
978 if (QFileInfo(f1).exists())
982 RS_DEBUG->print("File %s doesn't exist.", (const char *)QFile::encodeName(f1));
984 // QString f2 = fiDxf.dirPath(true) + "/" + fiBitmap.fileName();
985 QString f2 = fiDxf.absolutePath() + "/" + fiBitmap.fileName();
987 if (QFileInfo(f2).exists())
993 RS_DEBUG->print("File %s doesn't exist.", (const char *)QFile::encodeName(f2));
998 // Also link images in subcontainers (e.g. inserts):
999 for(RS_Entity * e=graphic->firstEntity(RS2::ResolveNone); e!=NULL;
1000 e=graphic->nextEntity(RS2::ResolveNone))
1002 if (e->rtti() == RS2::EntityImage)
1004 RS_Image * img = (RS_Image *)e;
1006 if (img->getHandle() == handle)
1008 img->setFile(sfile);
1009 RS_DEBUG->print("image found: %s", (const char *)QFile::encodeName(img->getFile()));
1015 // update images in blocks:
1016 for(uint i=0; i<graphic->countBlocks(); ++i)
1018 RS_Block * b = graphic->blockAt(i);
1020 for(RS_Entity * e=b->firstEntity(RS2::ResolveNone); e!=NULL; e=b->nextEntity(RS2::ResolveNone))
1022 if (e->rtti() == RS2::EntityImage)
1024 RS_Image * img = (RS_Image *)e;
1026 if (img->getHandle() == handle)
1028 img->setFile(sfile);
1029 RS_DEBUG->print("image in block found: %s",
1030 (const char*)QFile::encodeName(img->getFile()));
1037 RS_DEBUG->print("linking image: OK");
1041 * Finishes a hatch entity.
1043 void RS_FilterDXF::endEntity()
1045 RS_DEBUG->print("RS_FilterDXF::endEntity");
1049 RS_DEBUG->print("hatch->update()");
1051 if (hatch->validate())
1055 graphic->removeEntity(hatch);
1056 RS_DEBUG->print(RS_Debug::D_ERROR, "RS_FilterDXF::endEntity(): updating hatch failed: invalid hatch area");
1063 /*virtual*/ void RS_FilterDXF::endSequence()
1068 * Sets a vector variable from the DXF file.
1070 void RS_FilterDXF::setVariableVector(const char * key, double v1, double v2, double v3, int code)
1072 RS_DEBUG->print("RS_FilterDXF::setVariableVector");
1074 // update document's variable list:
1075 if (currentContainer->rtti() == RS2::EntityGraphic)
1076 ((RS_Graphic *)currentContainer)->addVariable(QString(key), Vector(v1, v2, v3), code);
1080 * Sets a string variable from the DXF file.
1082 void RS_FilterDXF::setVariableString(const char * key, const char * value, int code)
1084 RS_DEBUG->print("RS_FilterDXF::setVariableString");
1086 // update local DXF variable list:
1087 variables.add(QString(key), QString(value), code);
1089 // update document's variable list:
1090 if (currentContainer->rtti()==RS2::EntityGraphic) {
1091 ((RS_Graphic*)currentContainer)->addVariable(QString(key),
1092 QString(value), code);
1099 * Sets an int variable from the DXF file.
1101 void RS_FilterDXF::setVariableInt(const char* key, int value, int code) {
1102 RS_DEBUG->print("RS_FilterDXF::setVariableInt");
1104 // update document's variable list:
1105 if (currentContainer->rtti()==RS2::EntityGraphic) {
1106 ((RS_Graphic*)currentContainer)->addVariable(QString(key),
1114 * Sets a double variable from the DXF file.
1116 void RS_FilterDXF::setVariableDouble(const char* key, double value, int code) {
1117 RS_DEBUG->print("RS_FilterDXF::setVariableDouble");
1119 // update document's variable list:
1120 if (currentContainer->rtti() == RS2::EntityGraphic)
1122 ((RS_Graphic *)currentContainer)->addVariable(QString(key), value, code);
1127 * Implementation of the method used for RS_Export to communicate
1130 * @param file Full path to the DXF file that will be written.
1132 bool RS_FilterDXF::fileExport(RS_Graphic & g, const QString & file, RS2::FormatType type)
1134 RS_DEBUG->print("RS_FilterDXF::fileExport: exporting file '%s'...",
1135 (const char *)QFile::encodeName(file));
1136 RS_DEBUG->print("RS_FilterDXF::fileExport: file type '%d'", (int)type);
1141 // check if we can write to that directory:
1142 // QString path = QFileInfo(file).dirPath(true);
1143 QString path = QFileInfo(file).absolutePath();
1145 if (QFileInfo(path).isWritable() == false)
1147 RS_DEBUG->print("RS_FilterDXF::fileExport: can't write file: no permission");
1153 // set version for DXF filter:
1154 DL_Codes::version exportVersion;
1156 if (type == RS2::FormatDXF12)
1158 exportVersion = DL_Codes::AC1009;
1162 exportVersion = DL_Codes::AC1015;
1165 //DL_WriterA* dw = dxf.out(file, VER_R12);
1166 DL_WriterA * dw = dxf.out((const char *)QFile::encodeName(file), exportVersion);
1170 RS_DEBUG->print("RS_FilterDXF::fileExport: can't write file");
1175 RS_DEBUG->print("writing headers...");
1176 dxf.writeHeader(*dw);
1179 RS_DEBUG->print("writing variables...");
1180 writeVariables(*dw);
1183 RS_DEBUG->print("writing tables...");
1184 dw->sectionTables();
1187 dxf.writeVPort(*dw);
1190 RS_DEBUG->print("writing line types...");
1191 int numLT = (int)RS2::BorderLineX2 - (int)RS2::LineByBlock;
1193 if (type == RS2::FormatDXF12)
1196 dw->tableLineTypes(numLT);
1198 for(int t=(int)RS2::LineByBlock; t<=(int)RS2::BorderLineX2; ++t)
1200 if ((RS2::LineType)t != RS2::NoPen)
1201 writeLineType(*dw, (RS2::LineType)t);
1207 RS_DEBUG->print("writing layers...");
1208 dw->tableLayers(graphic->countLayers());
1210 for(uint i=0; i<graphic->countLayers(); ++i)
1212 RS_Layer * l = graphic->layerAt(i);
1219 RS_DEBUG->print("writing styles...");
1220 dxf.writeStyle(*dw);
1223 RS_DEBUG->print("writing views...");
1227 RS_DEBUG->print("writing ucs...");
1231 RS_DEBUG->print("writing appid...");
1233 writeAppid(*dw, "ACAD");
1237 RS_DEBUG->print("writing dim styles...");
1238 dxf.writeDimStyle(*dw,
1239 graphic->getVariableDouble("$DIMASZ", 2.5),
1240 graphic->getVariableDouble("$DIMEXE", 1.25),
1241 graphic->getVariableDouble("$DIMEXO", 0.625),
1242 graphic->getVariableDouble("$DIMGAP", 0.625),
1243 graphic->getVariableDouble("$DIMTXT", 2.5));
1246 if (type == RS2::FormatDXF)
1248 RS_DEBUG->print("writing block records...");
1249 dxf.writeBlockRecord(*dw);
1251 for(uint i=0; i<graphic->countBlocks(); ++i)
1253 RS_Block * blk = graphic->blockAt(i);
1254 dxf.writeBlockRecord(*dw, std::string((const char *)blk->getName().toLocal8Bit()));
1257 //writeBlock(*dw, blk);
1258 dw->dxfString( 0, "BLOCK_RECORD");
1259 //dw.dxfHex(5, 0x1F);
1262 dw->dxfString(100, "AcDbSymbolTableRecord");
1263 dw->dxfString(100, "AcDbBlockTableRecord");
1264 dw->dxfString( 2, blk->getName().toLocal8Bit());
1273 RS_DEBUG->print("writing end of section TABLES...");
1277 RS_DEBUG->print("writing blocks...");
1278 dw->sectionBlocks();
1280 if (type == RS2::FormatDXF)
1282 RS_Block b1(graphic, RS_BlockData("*Model_Space", Vector(0.0, 0.0), false));
1283 writeBlock(*dw, &b1);
1284 RS_Block b2(graphic, RS_BlockData("*Paper_Space", Vector(0.0, 0.0), false));
1285 writeBlock(*dw, &b2);
1286 RS_Block b3(graphic, RS_BlockData("*Paper_Space0", Vector(0.0, 0.0), false));
1287 writeBlock(*dw, &b3);
1290 for(uint i=0; i<graphic->countBlocks(); ++i)
1292 RS_Block * blk = graphic->blockAt(i);
1294 // Save block if it's not a model or paper space:
1295 // Careful: other blocks with * / $ exist
1296 //if (blk->getName().at(0)!='*' &&
1297 // blk->getName().at(0)!='$') {
1298 writeBlock(*dw, blk);
1304 // Section ENTITIES:
1305 RS_DEBUG->print("writing section ENTITIES...");
1306 dw->sectionEntities();
1308 for(RS_Entity * e=graphic->firstEntity(RS2::ResolveNone); e!=NULL;
1309 e=graphic->nextEntity(RS2::ResolveNone))
1311 writeEntity(*dw, e);
1314 RS_DEBUG->print("writing end of section ENTITIES...");
1317 if (type == RS2::FormatDXF)
1319 RS_DEBUG->print("writing section OBJECTS...");
1320 dxf.writeObjects(*dw);
1322 // IMAGEDEF's from images in entities and images in blocks
1323 QStringList written;
1325 for(uint i=0; i<graphic->countBlocks(); ++i)
1327 RS_Block * block = graphic->blockAt(i);
1329 for(RS_Entity * e=block->firstEntity(RS2::ResolveAll); e!=NULL;
1330 e=block->nextEntity(RS2::ResolveAll))
1332 if (e->rtti() == RS2::EntityImage)
1334 RS_Image * img = ((RS_Image *)e);
1336 if (written.contains(file) == 0 && img->getHandle() != 0)
1338 writeImageDef(*dw, img);
1339 written.append(img->getFile());
1345 for(RS_Entity * e=graphic->firstEntity(RS2::ResolveNone); e!=NULL;
1346 e=graphic->nextEntity(RS2::ResolveNone))
1348 if (e->rtti() == RS2::EntityImage)
1350 RS_Image * img = ((RS_Image *)e);
1352 if (written.contains(file) == 0 && img->getHandle() != 0)
1354 writeImageDef(*dw, img);
1355 written.append(img->getFile());
1359 RS_DEBUG->print("writing end of section OBJECTS...");
1360 dxf.writeObjectsEnd(*dw);
1363 RS_DEBUG->print("writing EOF...");
1366 RS_DEBUG->print("close..");
1371 // check if file was actually written (strange world of windoze xp):
1372 if (QFileInfo(file).exists() == false)
1374 RS_DEBUG->print("RS_FilterDXF::fileExport: file could not be written");
1382 * Writes all known variable settings to the DXF file.
1384 void RS_FilterDXF::writeVariables(DL_WriterA & dw)
1386 // Q3DictIterator<RS_Variable> it(graphic->getVariableDict());
1387 QHashIterator<QString, RS_Variable *> it(graphic->getVariableDict());
1389 // for (; it.current(); ++it)
1390 while (it.hasNext())
1394 // exclude variables that are not known to DXF 12:
1395 if (!DL_Dxf::checkVariable(it.key().toLatin1(), dxf.getVersion()))
1398 if (it.key() != "$ACADVER" && it.key() != "$HANDSEED")
1400 dw.dxfString(9, (const char *)it.key().toAscii().data());
1402 switch (it.value()->getType())
1404 case RS2::VariableVoid:
1406 case RS2::VariableInt:
1407 dw.dxfInt(it.value()->getCode(), it.value()->getInt());
1409 case RS2::VariableDouble:
1410 dw.dxfReal(it.value()->getCode(), it.value()->getDouble());
1412 case RS2::VariableString:
1413 dw.dxfString(it.value()->getCode(), (const char *)it.value()->getString().toAscii().data());
1415 case RS2::VariableVector:
1416 dw.dxfReal(it.value()->getCode(), it.value()->getVector().x);
1417 dw.dxfReal(it.value()->getCode() + 10, it.value()->getVector().y);
1419 if (isVariableTwoDimensional(it.key()) == false)
1420 dw.dxfReal(it.value()->getCode() + 20, it.value()->getVector().z);
1431 * Writes one layer to the DXF file.
1433 * @todo Add support for unicode layer names
1435 void RS_FilterDXF::writeLayer(DL_WriterA & dw, RS_Layer * l)
1439 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_FilterDXF::writeLayer: layer is NULL");
1443 RS_DEBUG->print("RS_FilterDXF::writeLayer %s", l->getName().toLatin1().data());
1445 dxf.writeLayer(dw, DL_LayerData((const char *)l->getName().toLocal8Bit(),
1446 l->isFrozen() + (l->isLocked() << 2)), DL_Attributes(std::string(""),
1447 colorToNumber(l->getPen().getColor()), widthToNumber(l->getPen().getWidth()),
1448 (const char *)lineTypeToName(l->getPen().getLineType()).toLocal8Bit()));
1450 RS_DEBUG->print("RS_FilterDXF::writeLayer end");
1454 * Writes a line type to the DXF file.
1456 void RS_FilterDXF::writeLineType(DL_WriterA & dw, RS2::LineType t)
1458 dxf.writeLineType(dw, DL_LineTypeData((const char *)lineTypeToName(t).toLocal8Bit(), 0));
1464 * Writes an application id to the DXF file.
1466 * @param appid Application ID (e.g. "QCad").
1468 void RS_FilterDXF::writeAppid(DL_WriterA& dw, const char* appid) {
1469 dxf.writeAppid(dw, appid);
1475 * Writes a block (just the definition, not the entities in it).
1477 void RS_FilterDXF::writeBlock(DL_WriterA& dw, RS_Block* blk) {
1479 RS_DEBUG->print(RS_Debug::D_WARNING,
1480 "RS_FilterDXF::writeBlock: Block is NULL");
1484 RS_DEBUG->print("writing block: %s", (const char*)blk->getName().toLocal8Bit());
1487 DL_BlockData((const char*)blk->getName().toLocal8Bit(), 0,
1488 blk->getBasePoint().x,
1489 blk->getBasePoint().y,
1490 blk->getBasePoint().z));
1491 for (RS_Entity* e=blk->firstEntity(RS2::ResolveNone);
1493 e=blk->nextEntity(RS2::ResolveNone)) {
1496 dxf.writeEndBlock(dw, (const char*)blk->getName().toLocal8Bit());
1502 * Writes the given entity to the DXF file.
1504 void RS_FilterDXF::writeEntity(DL_WriterA& dw, RS_Entity* e) {
1505 writeEntity(dw, e, getEntityAttributes(e));
1510 * Writes the given entity to the DXF file.
1512 void RS_FilterDXF::writeEntity(DL_WriterA& dw, RS_Entity* e,
1513 const DL_Attributes& attrib) {
1515 if (e==NULL || e->getFlag(RS2::FlagUndone)) {
1518 RS_DEBUG->print("writing Entity");
1520 switch (e->rtti()) {
1521 case RS2::EntityPoint:
1522 writePoint(dw, (RS_Point*)e, attrib);
1524 case RS2::EntityLine:
1525 writeLine(dw, (RS_Line*)e, attrib);
1527 case RS2::EntityPolyline:
1528 writePolyline(dw, (RS_Polyline*)e, attrib);
1530 case RS2::EntitySpline:
1531 writeSpline(dw, (RS_Spline*)e, attrib);
1533 case RS2::EntityVertex:
1535 case RS2::EntityCircle:
1536 writeCircle(dw, (RS_Circle*)e, attrib);
1538 case RS2::EntityArc:
1539 writeArc(dw, (RS_Arc*)e, attrib);
1541 case RS2::EntityEllipse:
1542 writeEllipse(dw, (RS_Ellipse*)e, attrib);
1544 case RS2::EntityInsert:
1545 writeInsert(dw, (RS_Insert*)e, attrib);
1547 case RS2::EntityText:
1548 writeText(dw, (RS_Text*)e, attrib);
1551 case RS2::EntityDimAligned:
1552 case RS2::EntityDimAngular:
1553 case RS2::EntityDimLinear:
1554 case RS2::EntityDimRadial:
1555 case RS2::EntityDimDiametric:
1556 writeDimension(dw, (RS_Dimension*)e, attrib);
1558 case RS2::EntityDimLeader:
1559 writeLeader(dw, (RS_Leader*)e, attrib);
1561 case RS2::EntityHatch:
1562 writeHatch(dw, (RS_Hatch*)e, attrib);
1564 case RS2::EntityImage:
1565 writeImage(dw, (RS_Image*)e, attrib);
1567 case RS2::EntitySolid:
1568 writeSolid(dw, (RS_Solid*)e, attrib);
1571 #ifndef RS_NO_COMPLEX_ENTITIES
1573 case RS2::EntityContainer:
1574 writeEntityContainer(dw, (RS_EntityContainer*)e, attrib);
1586 * Writes the given Point entity to the file.
1588 void RS_FilterDXF::writePoint(DL_WriterA& dw, RS_Point* p,
1589 const DL_Attributes& attrib) {
1592 DL_PointData(p->getPos().x,
1600 * Writes the given Line( entity to the file.
1602 void RS_FilterDXF::writeLine(DL_WriterA& dw, RS_Line* l,
1603 const DL_Attributes& attrib) {
1606 DL_LineData(l->getStartpoint().x,
1607 l->getStartpoint().y,
1618 * Writes the given polyline entity to the file.
1620 void RS_FilterDXF::writePolyline(DL_WriterA& dw,
1622 const DL_Attributes& attrib) {
1624 int count = l->count();
1625 if (l->isClosed()==false) {
1631 DL_PolylineData(count,
1636 RS_Entity* nextEntity = 0;
1637 RS_AtomicEntity* ae = NULL;
1638 RS_Entity* lastEntity = l->lastEntity(RS2::ResolveNone);
1639 for (RS_Entity* v=l->firstEntity(RS2::ResolveNone);
1643 nextEntity = l->nextEntity(RS2::ResolveNone);
1645 if (!v->isAtomic()) {
1649 ae = (RS_AtomicEntity*)v;
1654 if (v->rtti()==RS2::EntityArc) {
1655 bulge = ((RS_Arc*)v)->getBulge();
1658 DL_VertexData(ae->getStartpoint().x,
1659 ae->getStartpoint().y,
1665 //if (dxf.getVersion()==VER_R12) {
1666 if (nextEntity!=NULL) {
1667 if (nextEntity->rtti()==RS2::EntityArc) {
1668 bulge = ((RS_Arc*)nextEntity)->getBulge();
1675 if (v->rtti()==RS2::EntityArc) {
1676 bulge = ((RS_Arc*)v)->getBulge();
1681 if (l->isClosed()==false || v!=lastEntity) {
1683 DL_VertexData(ae->getEndpoint().x,
1684 ae->getEndpoint().y,
1689 dxf.writePolylineEnd(dw);
1695 * Writes the given spline entity to the file.
1697 void RS_FilterDXF::writeSpline(DL_WriterA & dw, RS_Spline * s, const DL_Attributes & attrib)
1699 // split spline into atomic entities for DXF R12:
1700 if (dxf.getVersion() == VER_R12)
1702 writeAtomicEntities(dw, s, attrib, RS2::ResolveNone);
1706 if (s->getNumberOfControlPoints() < s->getDegree() + 1)
1708 RS_DEBUG->print(RS_Debug::D_ERROR, "RS_FilterDXF::writeSpline: "
1709 "Discarding spline: not enough control points given.");
1713 // Number of control points:
1714 int numCtrl = s->getNumberOfControlPoints();
1716 // Number of knots (= number of control points + spline degree + 1)
1717 int numKnots = numCtrl + s->getDegree() + 1;
1726 // write spline header:
1727 dxf.writeSpline(dw, DL_SplineData(s->getDegree(), numKnots, numCtrl, flags), attrib);
1729 // write spline knots:
1730 QList<Vector> cp = s->getControlPoints();
1731 QList<Vector>::iterator it;
1733 int k = s->getDegree() + 1;
1736 for(int i=1; i<=numKnots; i++)
1739 kd = DL_KnotData(0.0);
1740 else if (i <= numKnots - k)
1741 kd = DL_KnotData(1.0 / (numKnots - 2 * k + 1) * (i - k));
1743 kd = DL_KnotData(1.0);
1745 dxf.writeKnot(dw, kd);
1748 // write spline control points:
1749 for(it=cp.begin(); it!=cp.end(); ++it)
1751 dxf.writeControlPoint(dw, DL_ControlPointData((*it).x, (*it).y, 0.0));
1756 * Writes the given circle entity to the file.
1758 void RS_FilterDXF::writeCircle(DL_WriterA& dw, RS_Circle* c,
1759 const DL_Attributes& attrib) {
1762 DL_CircleData(c->getCenter().x,
1772 void RS_FilterDXF::writeArc(DL_WriterA& dw, RS_Arc* a,
1773 const DL_Attributes& attrib) {
1775 if (a->isReversed()) {
1776 a1 = a->getAngle2()*ARAD;
1777 a2 = a->getAngle1()*ARAD;
1779 a1 = a->getAngle1()*ARAD;
1780 a2 = a->getAngle2()*ARAD;
1784 DL_ArcData(a->getCenter().x,
1793 void RS_FilterDXF::writeEllipse(DL_WriterA& dw, RS_Ellipse* s,
1794 const DL_Attributes& attrib) {
1795 if (s->isReversed()) {
1798 DL_EllipseData(s->getCenter().x,
1811 DL_EllipseData(s->getCenter().x,
1824 void RS_FilterDXF::writeInsert(DL_WriterA & dw, RS_Insert * i, const DL_Attributes & attrib)
1826 dxf.writeInsert(dw, DL_InsertData(i->getName().toLatin1().data(),
1827 i->getInsertionPoint().x, i->getInsertionPoint().y, 0.0,
1828 i->getScale().x, i->getScale().y, 0.0,
1829 i->getAngle() * ARAD, i->getCols(), i->getRows(),
1830 i->getSpacing().x, i->getSpacing().y),
1834 void RS_FilterDXF::writeText(DL_WriterA & dw, RS_Text * t, const DL_Attributes & attrib)
1836 if (dxf.getVersion()==VER_R12)
1841 if (t->getHAlign()==RS2::HAlignLeft) {
1843 } else if (t->getHAlign()==RS2::HAlignCenter) {
1845 } else if (t->getHAlign()==RS2::HAlignRight) {
1849 if (t->getVAlign()==RS2::VAlignTop) {
1851 } else if (t->getVAlign()==RS2::VAlignMiddle) {
1853 } else if (t->getVAlign()==RS2::VAlignBottom) {
1859 DL_TextData(t->getInsertionPoint().x,
1860 t->getInsertionPoint().y,
1862 t->getInsertionPoint().x,
1863 t->getInsertionPoint().y,
1869 (const char*)toDxfString(
1870 t->getText()).toLocal8Bit(),
1871 (const char*)t->getStyle().toLocal8Bit(),
1877 int attachmentPoint=1;
1879 if (t->getHAlign()==RS2::HAlignLeft) {
1881 } else if (t->getHAlign()==RS2::HAlignCenter) {
1883 } else if (t->getHAlign()==RS2::HAlignRight) {
1887 if (t->getVAlign()==RS2::VAlignTop) {
1889 } else if (t->getVAlign()==RS2::VAlignMiddle) {
1891 } else if (t->getVAlign()==RS2::VAlignBottom) {
1897 DL_MTextData(t->getInsertionPoint().x,
1898 t->getInsertionPoint().y,
1903 t->getDrawingDirection(),
1904 t->getLineSpacingStyle(),
1905 t->getLineSpacingFactor(),
1906 (const char*)toDxfString(
1907 t->getText()).toLocal8Bit(),
1908 (const char*)t->getStyle().toLocal8Bit(),
1916 void RS_FilterDXF::writeDimension(DL_WriterA& dw, RS_Dimension* d,
1917 const DL_Attributes& attrib) {
1919 // split hatch into atomic entities:
1920 if (dxf.getVersion()==VER_R12) {
1921 writeAtomicEntities(dw, d, attrib, RS2::ResolveNone);
1926 int attachmentPoint=1;
1927 if (d->getHAlign()==RS2::HAlignLeft) {
1929 } else if (d->getHAlign()==RS2::HAlignCenter) {
1931 } else if (d->getHAlign()==RS2::HAlignRight) {
1934 if (d->getVAlign()==RS2::VAlignTop) {
1936 } else if (d->getVAlign()==RS2::VAlignMiddle) {
1938 } else if (d->getVAlign()==RS2::VAlignBottom) {
1942 switch (d->rtti()) {
1943 case RS2::EntityDimAligned:
1946 case RS2::EntityDimLinear:
1949 case RS2::EntityDimRadial:
1952 case RS2::EntityDimDiametric:
1960 DL_DimensionData dimData(d->getDefinitionPoint().x,
1961 d->getDefinitionPoint().y,
1963 d->getMiddleOfText().x,
1964 d->getMiddleOfText().y,
1968 d->getLineSpacingStyle(),
1969 d->getLineSpacingFactor(),
1970 (const char*)toDxfString(
1971 d->getText()).toLocal8Bit(),
1972 (const char*)d->getStyle().toLocal8Bit(),
1975 if (d->rtti()==RS2::EntityDimAligned) {
1976 RS_DimAligned* da = (RS_DimAligned*)d;
1978 DL_DimAlignedData dimAlignedData(da->getExtensionPoint1().x,
1979 da->getExtensionPoint1().y,
1981 da->getExtensionPoint2().x,
1982 da->getExtensionPoint2().y,
1985 dxf.writeDimAligned(dw, dimData, dimAlignedData, attrib);
1986 } else if (d->rtti()==RS2::EntityDimLinear) {
1987 RS_DimLinear* dl = (RS_DimLinear*)d;
1989 DL_DimLinearData dimLinearData(dl->getExtensionPoint1().x,
1990 dl->getExtensionPoint1().y,
1992 dl->getExtensionPoint2().x,
1993 dl->getExtensionPoint2().y,
1998 dxf.writeDimLinear(dw, dimData, dimLinearData, attrib);
1999 } else if (d->rtti()==RS2::EntityDimRadial) {
2000 RS_DimRadial* dr = (RS_DimRadial*)d;
2002 DL_DimRadialData dimRadialData(dr->getDefinitionPoint().x,
2003 dr->getDefinitionPoint().y,
2007 dxf.writeDimRadial(dw, dimData, dimRadialData, attrib);
2008 } else if (d->rtti()==RS2::EntityDimDiametric) {
2009 RS_DimDiametric* dr = (RS_DimDiametric*)d;
2011 DL_DimDiametricData dimDiametricData(dr->getDefinitionPoint().x,
2012 dr->getDefinitionPoint().y,
2016 dxf.writeDimDiametric(dw, dimData, dimDiametricData, attrib);
2017 } else if (d->rtti()==RS2::EntityDimAngular) {
2018 RS_DimAngular* da = (RS_DimAngular*)d;
2020 DL_DimAngularData dimAngularData(da->getDefinitionPoint1().x,
2021 da->getDefinitionPoint1().y,
2023 da->getDefinitionPoint2().x,
2024 da->getDefinitionPoint2().y,
2026 da->getDefinitionPoint3().x,
2027 da->getDefinitionPoint3().y,
2029 da->getDefinitionPoint4().x,
2030 da->getDefinitionPoint4().y,
2033 dxf.writeDimAngular(dw, dimData, dimAngularData, attrib);
2039 void RS_FilterDXF::writeLeader(DL_WriterA& dw, RS_Leader* l,
2040 const DL_Attributes& attrib) {
2044 DL_LeaderData(l->hasArrowHead(),
2054 for (RS_Entity* v=l->firstEntity(RS2::ResolveNone);
2056 v=l->nextEntity(RS2::ResolveNone)) {
2058 // Write line verties:
2059 if (v->rtti()==RS2::EntityLine) {
2060 RS_Line* l = (RS_Line*)v;
2062 dxf.writeLeaderVertex(
2064 DL_LeaderVertexData(l->getStartpoint().x,
2065 l->getStartpoint().y,
2069 dxf.writeLeaderVertex(
2071 DL_LeaderVertexData(l->getEndpoint().x,
2077 RS_DEBUG->print(RS_Debug::D_WARNING,
2078 "dropping leader with no vertices");
2083 void RS_FilterDXF::writeHatch(DL_WriterA& dw, RS_Hatch* h,
2084 const DL_Attributes& attrib) {
2086 // split hatch into atomic entities:
2087 if (dxf.getVersion()==VER_R12) {
2088 writeAtomicEntities(dw, h, attrib, RS2::ResolveAll);
2092 bool writeIt = true;
2093 if (h->countLoops()>0) {
2094 // check if all of the loops contain entities:
2095 for (RS_Entity* l=h->firstEntity(RS2::ResolveNone);
2097 l=h->nextEntity(RS2::ResolveNone)) {
2099 if (l->isContainer() && !l->getFlag(RS2::FlagTemp)) {
2100 if (l->count()==0) {
2110 RS_DEBUG->print(RS_Debug::D_WARNING,
2111 "RS_FilterDXF::writeHatch: Dropping Hatch");
2113 DL_HatchData data(h->countLoops(),
2117 (const char*)h->getPattern().toLocal8Bit());
2118 dxf.writeHatch1(dw, data, attrib);
2120 for (RS_Entity* l=h->firstEntity(RS2::ResolveNone);
2122 l=h->nextEntity(RS2::ResolveNone)) {
2124 // Write hatch loops:
2125 if (l->isContainer() && !l->getFlag(RS2::FlagTemp)) {
2126 RS_EntityContainer* loop = (RS_EntityContainer*)l;
2127 DL_HatchLoopData lData(loop->count());
2128 dxf.writeHatchLoop1(dw, lData);
2130 for (RS_Entity* ed=loop->firstEntity(RS2::ResolveNone);
2132 ed=loop->nextEntity(RS2::ResolveNone)) {
2134 // Write hatch loop edges:
2135 if (ed->rtti()==RS2::EntityLine) {
2136 RS_Line* ln = (RS_Line*)ed;
2139 DL_HatchEdgeData(ln->getStartpoint().x,
2140 ln->getStartpoint().y,
2141 ln->getEndpoint().x,
2142 ln->getEndpoint().y));
2143 } else if (ed->rtti()==RS2::EntityArc) {
2144 RS_Arc* ar = (RS_Arc*)ed;
2145 if (!ar->isReversed()) {
2148 DL_HatchEdgeData(ar->getCenter().x,
2157 DL_HatchEdgeData(ar->getCenter().x,
2160 2*M_PI-ar->getAngle1(),
2161 2*M_PI-ar->getAngle2(),
2164 } else if (ed->rtti()==RS2::EntityCircle) {
2165 RS_Circle* ci = (RS_Circle*)ed;
2168 DL_HatchEdgeData(ci->getCenter().x,
2176 dxf.writeHatchLoop2(dw, lData);
2179 dxf.writeHatch2(dw, data, attrib);
2186 void RS_FilterDXF::writeSolid(DL_WriterA& dw, RS_Solid* s,
2187 const DL_Attributes& attrib) {
2189 // split solid into line entities:
2190 //if (dxf.getVersion()==VER_R12) {
2191 for (int i=0; i<3; ++i) {
2194 DL_LineData(s->getCorner(i).x,
2197 s->getCorner((i+1)%3).x,
2198 s->getCorner((i+1)%3).y,
2207 void RS_FilterDXF::writeImage(DL_WriterA& dw, RS_Image* i,
2208 const DL_Attributes& attrib) {
2209 int handle = dxf.writeImage(
2211 DL_ImageData(std::string(""),
2212 i->getInsertionPoint().x,
2213 i->getInsertionPoint().y,
2227 i->setHandle(handle);
2232 void RS_FilterDXF::writeEntityContainer(DL_WriterA& dw, RS_EntityContainer* con,
2233 const DL_Attributes& /*attrib*/) {
2237 // Creating an unique ID from the element ID
2238 int tmp, c=1; // tmp = temporary var c = counter var
2243 blkName.append((char) tmp %10 + 48);
2252 dxf.writeBlockRecord(dw);
2253 dw.dxfString( 0, "BLOCK_RECORD");
2257 dw.dxfString(100, "AcDbSymbolTableRecord");
2258 dw.dxfString(100, "AcDbBlockTableRecord");
2259 dw.dxfString( 2, blkName.toLatin1());
2261 dw.dxfString(0, "ENDTAB");
2264 RS_BlockData blkdata(blkName, Vector(0,0), false);
2266 RS_Block* blk = new RS_Block(graphic, blkdata);
2268 for (RS_Entity* e1 = con->firstEntity(); e1 != NULL;
2269 e1 = con->nextEntity() ) {
2272 writeBlock(dw, blk);
2280 * Writes the atomic entities of the given cotnainer to the file.
2282 void RS_FilterDXF::writeAtomicEntities(DL_WriterA& dw, RS_EntityContainer* c,
2283 const DL_Attributes& attrib,
2284 RS2::ResolveLevel level) {
2286 for (RS_Entity* e=c->firstEntity(level);
2288 e=c->nextEntity(level)) {
2290 writeEntity(dw, e, attrib);
2295 * Writes an IMAGEDEF object into an OBJECT section.
2297 void RS_FilterDXF::writeImageDef(DL_WriterA& dw, RS_Image* i) {
2298 if (i==NULL || i->getFlag(RS2::FlagUndone)) {
2305 DL_ImageData((const char*)i->getFile().toLocal8Bit(),
2306 i->getInsertionPoint().x,
2307 i->getInsertionPoint().y,
2325 * Sets the entities attributes according to the attributes
2326 * that come from a DXF file.
2328 void RS_FilterDXF::setEntityAttributes(RS_Entity* entity,
2329 const DL_Attributes& attrib) {
2330 RS_DEBUG->print("RS_FilterDXF::setEntityAttributes");
2333 pen.setColor(Qt::black);
2334 pen.setLineType(RS2::SolidLine);
2337 if (attrib.getLayer().empty()) {
2338 entity->setLayer("0");
2340 // add layer in case it doesn't exist:
2341 if (graphic->findLayer(attrib.getLayer().c_str())==NULL) {
2342 addLayer(DL_LayerData(attrib.getLayer(), 0));
2344 entity->setLayer(attrib.getLayer().c_str());
2348 pen.setColor(numberToColor(attrib.getColor()));
2351 pen.setLineType(nameToLineType(attrib.getLineType().c_str()));
2354 pen.setWidth(numberToWidth(attrib.getWidth()));
2356 entity->setPen(pen);
2357 RS_DEBUG->print("RS_FilterDXF::setEntityAttributes: OK");
2361 * Gets the entities attributes as a DL_Attributes object.
2363 DL_Attributes RS_FilterDXF::getEntityAttributes(RS_Entity * entity)
2366 RS_Layer * layer = entity->getLayer();
2370 layerName = layer->getName();
2374 RS_Pen pen = entity->getPen(false);
2377 int color = colorToNumber(pen.getColor());
2378 //printf("Color is: %s -> %d\n", pen.getColor().name().toLatin1(), color);
2381 QString lineType = lineTypeToName(pen.getLineType());
2384 int width = widthToNumber(pen.getWidth());
2386 DL_Attributes attrib(layerName.toLatin1().data(), color, width, lineType.toLatin1().data());
2392 * @return Pen with the same attributes as 'attrib'.
2394 RS_Pen RS_FilterDXF::attributesToPen(const DL_Attributes & attrib) const
2397 printf("converting Color %d to %s\n",
2398 attrib.getColor(), numberToColor(attrib.getColor()).name().toLatin1());
2401 RS_Pen pen(numberToColor(attrib.getColor()),
2402 numberToWidth(attrib.getWidth()),
2403 nameToLineType(attrib.getLineType().c_str()));
2410 * Converts a color index (num) into a RS_Color object.
2411 * Please refer to the dxflib documentation for details.
2413 * @param num Color number.
2414 * @param comp Compatibility with older QCad versions (1.5.3 and older)
2416 RS_Color RS_FilterDXF::numberToColor(int num, bool comp) {
2417 // Compatibility with QCad 1.5.3 and older:
2424 return Qt::darkBlue;
2427 return Qt::darkGreen;
2430 return Qt::darkCyan;
2436 return Qt::darkMagenta;
2439 return Qt::darkYellow;
2442 return Qt::lightGray;
2445 return Qt::darkGray;
2473 return RS_Color(RS2::FlagByBlock);
2474 } else if (num==256) {
2475 return RS_Color(RS2::FlagByLayer);
2476 } else if (num<=255 && num>=0) {
2477 return RS_Color((int)(dxfColors[num][0]*255),
2478 (int)(dxfColors[num][1]*255),
2479 (int)(dxfColors[num][2]*255));
2481 RS_DEBUG->print(RS_Debug::D_WARNING,
2482 "RS_FilterDXF::numberToColor: Invalid color number given.");
2483 return RS_Color(RS2::FlagByLayer);
2492 * Converts a color into a color number in the DXF palette.
2493 * The color that fits best is chosen.
2495 int RS_FilterDXF::colorToNumber(const RS_Color& col) {
2497 //printf("Searching color for %s\n", col.name().toLatin1());
2499 // Special color BYBLOCK:
2500 if (col.getFlag(RS2::FlagByBlock)) {
2504 // Special color BYLAYER
2505 else if (col.getFlag(RS2::FlagByLayer)) {
2509 // Special color black is not in the table but white represents both
2511 else if (col.red()==0 && col.green()==0 && col.blue()==0) {
2518 int diff=255*3; // smallest difference to a color in the table found so far
2520 // Run through the whole table and compare
2521 for (int i=1; i<=255; i++) {
2522 int d = abs(col.red()-(int)(dxfColors[i][0]*255))
2523 + abs(col.green()-(int)(dxfColors[i][1]*255))
2524 + abs(col.blue()-(int)(dxfColors[i][2]*255));
2528 printf("color %f,%f,%f is closer\n",
2540 //printf(" Found: %d, diff: %d\n", num, diff);
2546 * Converts a line type name (e.g. "CONTINUOUS") into a RS2::LineType
2549 RS2::LineType RS_FilterDXF::nameToLineType(const QString & name)
2551 QString uName = name.toUpper();
2553 // Standard linetypes for QCad II / AutoCAD
2554 if (uName.isEmpty() || uName == "BYLAYER")
2555 return RS2::LineByLayer;
2556 else if (uName == "BYBLOCK")
2557 return RS2::LineByBlock;
2558 else if (uName == "CONTINUOUS" || uName == "ACAD_ISO01W100")
2559 return RS2::SolidLine;
2560 else if (uName == "ACAD_ISO07W100" || uName == "DOT")
2561 return RS2::DotLine;
2562 else if (uName == "DOT2")
2563 return RS2::DotLine2;
2564 else if (uName == "DOTX2")
2565 return RS2::DotLineX2;
2566 else if (uName == "ACAD_ISO02W100" || uName == "ACAD_ISO03W100"
2567 || uName == "DASHED" || uName == "HIDDEN")
2568 return RS2::DashLine;
2569 else if (uName == "DASHED2" || uName == "HIDDEN2")
2570 return RS2::DashLine2;
2571 else if (uName == "DASHEDX2" || uName == "HIDDENX2")
2572 return RS2::DashLineX2;
2573 else if (uName == "ACAD_ISO10W100" || uName == "DASHDOT")
2574 return RS2::DashDotLine;
2575 else if (uName == "DASHDOT2")
2576 return RS2::DashDotLine2;
2577 else if (uName == "ACAD_ISO04W100" || uName == "DASHDOTX2")
2578 return RS2::DashDotLineX2;
2579 else if (uName == "ACAD_ISO12W100" || uName == "DIVIDE")
2580 return RS2::DivideLine;
2581 else if (uName == "DIVIDE2")
2582 return RS2::DivideLine2;
2583 else if (uName == "ACAD_ISO05W100" || uName == "DIVIDEX2")
2584 return RS2::DivideLineX2;
2585 else if (uName == "CENTER")
2586 return RS2::CenterLine;
2587 else if (uName == "CENTER2")
2588 return RS2::CenterLine2;
2589 else if (uName == "CENTERX2")
2590 return RS2::CenterLineX2;
2591 else if (uName == "BORDER")
2592 return RS2::BorderLine;
2593 else if (uName == "BORDER2")
2594 return RS2::BorderLine2;
2595 else if (uName == "BORDERX2")
2596 return RS2::BorderLineX2;
2598 return RS2::SolidLine;
2602 * Converts a RS_LineType into a name for a line type.
2604 QString RS_FilterDXF::lineTypeToName(RS2::LineType lineType)
2606 // Standard linetypes for QCad II / AutoCAD
2609 case RS2::SolidLine:
2610 return "CONTINUOUS";
2619 case RS2::DotLineX2:
2626 case RS2::DashLine2:
2629 case RS2::DashLineX2:
2633 case RS2::DashDotLine:
2636 case RS2::DashDotLine2:
2639 case RS2::DashDotLineX2:
2643 case RS2::DivideLine:
2646 case RS2::DivideLine2:
2649 case RS2::DivideLineX2:
2653 case RS2::CenterLine:
2656 case RS2::CenterLine2:
2659 case RS2::CenterLineX2:
2663 case RS2::BorderLine:
2666 case RS2::BorderLine2:
2669 case RS2::BorderLineX2:
2674 case RS2::LineByLayer:
2677 case RS2::LineByBlock:
2684 return "CONTINUOUS";
2690 * Converts a RS_LineType into a name for a line type.
2692 /*QString RS_FilterDXF::lineTypeToDescription(RS2::LineType lineType) {
2694 // Standard linetypes for QCad II / AutoCAD
2696 case RS2::SolidLine:
2697 return "Solid line";
2699 return "ISO Dashed __ __ __ __ __ __ __ __ __ __ _";
2701 return "ISO Dashed with Distance __ __ __ _";
2702 case RS2::DashDotLine:
2703 return "ISO Long Dashed Dotted ____ . ____ . __";
2704 case RS2::DashDotDotLine:
2705 return "ISO Long Dashed Double Dotted ____ .. __";
2706 case RS2::LineByLayer:
2708 case RS2::LineByBlock:
2714 return "CONTINUOUS";
2720 * Converts a line width number (e.g. 1) into a RS2::LineWidth.
2722 RS2::LineWidth RS_FilterDXF::numberToWidth(int num) {
2725 return RS2::WidthByLayer;
2728 return RS2::WidthByBlock;
2731 return RS2::WidthDefault;
2735 return RS2::Width00;
2737 return RS2::Width01;
2738 } else if (num<11) {
2739 return RS2::Width02;
2740 } else if (num<14) {
2741 return RS2::Width03;
2742 } else if (num<16) {
2743 return RS2::Width04;
2744 } else if (num<19) {
2745 return RS2::Width05;
2746 } else if (num<22) {
2747 return RS2::Width06;
2748 } else if (num<27) {
2749 return RS2::Width07;
2750 } else if (num<32) {
2751 return RS2::Width08;
2752 } else if (num<37) {
2753 return RS2::Width09;
2754 } else if (num<45) {
2755 return RS2::Width10;
2756 } else if (num<52) {
2757 return RS2::Width11;
2758 } else if (num<57) {
2759 return RS2::Width12;
2760 } else if (num<65) {
2761 return RS2::Width13;
2762 } else if (num<75) {
2763 return RS2::Width14;
2764 } else if (num<85) {
2765 return RS2::Width15;
2766 } else if (num<95) {
2767 return RS2::Width16;
2768 } else if (num<103) {
2769 return RS2::Width17;
2770 } else if (num<112) {
2771 return RS2::Width18;
2772 } else if (num<130) {
2773 return RS2::Width19;
2774 } else if (num<149) {
2775 return RS2::Width20;
2776 } else if (num<180) {
2777 return RS2::Width21;
2778 } else if (num<205) {
2779 return RS2::Width22;
2781 return RS2::Width23;
2785 return (RS2::LineWidth)num;
2791 * Converts a RS2::LineWidth into an int width.
2793 int RS_FilterDXF::widthToNumber(RS2::LineWidth width) {
2795 case RS2::WidthByLayer:
2798 case RS2::WidthByBlock:
2801 case RS2::WidthDefault:
2812 * Converts a native unicode string into a DXF encoded string.
2814 * DXF endoding includes the following special sequences:
2815 * - %%%c for a diameter sign
2816 * - %%%d for a degree sign
2817 * - %%%p for a plus/minus sign
2819 QString RS_FilterDXF::toDxfString(const QString & string)
2822 QString res = string;
2824 res = res.replace(QRegExp("\\n"), "\\P");
2826 res = res.replace(QRegExp(" "), "\\~");
2828 res = res.replace(QChar(0x2205), "%%c");
2830 res = res.replace(QChar(0x00B0), "%%d");
2832 res = res.replace(QChar(0x00B1), "%%p");
2837 for(int i=0; i<string.length(); ++i)
2839 int c = string.at(i).unicode();
2864 hex = QString("%1").arg(c, 4, 16);
2865 hex = hex.replace(' ', '0');
2866 res += QString("\\U+%1").arg(hex);
2869 res += string.at(i);
2879 * Converts a DXF encoded string into a native Unicode string.
2881 QString RS_FilterDXF::toNativeString(const QString & string)
2883 QString res = string;
2885 res = res.replace(QRegExp("\\\\P"), "\n");
2887 res = res.replace(QRegExp("\\\\~"), " ");
2889 res = res.replace(QRegExp("%%c"), QChar(0x2205));
2891 res = res.replace(QRegExp("%%d"), QChar(0x00B0));
2893 res = res.replace(QRegExp("%%p"), QChar(0x00B1));
2895 // Unicode characters:
2902 QRegExp regexp("\\\\U\\+[0-9A-Fa-f]{4,4}");
2903 // regexp.search(res);
2904 regexp.indexIn(res);
2909 uCode = cap.right(4).toInt(&ok, 16);
2910 // workaround for Qt 3.0.x:
2911 res.replace(QRegExp("\\\\U\\+" + cap.right(4)), QChar(uCode));
2913 //res.replace(cap, QChar(uCode));
2916 while (!cap.isNull());
2925 QRegExp regexp("%%[0-9]{3,3}");
2926 // regexp.search(res);
2927 regexp.indexIn(res);
2932 uCode = cap.right(3).toInt(&ok, 10);
2933 // workaround for Qt 3.0.x:
2934 res.replace(QRegExp("%%" + cap.right(3)), QChar(uCode));
2936 //res.replace(cap, QChar(uCode));
2939 while (!cap.isNull());
2941 // Ignore font tags:
2942 res = res.replace(QRegExp("\\\\f[0-9A-Za-z| ]{0,};"), "");
2945 res = res.replace("\\{", "#curly#");
2946 res = res.replace("{", "");
2947 res = res.replace("#curly#", "{");
2949 res = res.replace("\\}", "#curly#");
2950 res = res.replace("}", "");
2951 res = res.replace("#curly#", "}");
2953 RS_DEBUG->print("RS_FilterDXF::toNativeString:");
2954 RS_DEBUG->printUnicode(res);
2959 * Converts the given number from a DXF file into an AngleFormat enum.
2961 * @param num $DIMAUNIT from DXF (0: decimal deg, 1: deg/min/sec, 2: gradians,
2962 * 3: radians, 4: surveyor's units)
2964 * @ret Matching AngleFormat enum value.
2966 RS2::AngleFormat RS_FilterDXF::numberToAngleFormat(int num) {
2968 RS2::AngleFormat af;
2973 af = RS2::DegreesDecimal;
2976 af = RS2::DegreesMinutesSeconds;
2985 af = RS2::Surveyors;
2994 * Converts AngleFormat enum to DXF number.
2996 int RS_FilterDXF::angleFormatToNumber(RS2::AngleFormat af) {
3002 case RS2::DegreesDecimal:
3005 case RS2::DegreesMinutesSeconds:
3014 case RS2::Surveyors:
3025 * converts a DXF unit setting (e.g. INSUNITS) to a unit enum.
3027 RS2::Unit RS_FilterDXF::numberToUnit(int num) {
3043 return RS2::Millimeter;
3046 return RS2::Centimeter;
3052 return RS2::Kilometer;
3055 return RS2::Microinch;
3064 return RS2::Angstrom;
3067 return RS2::Nanometer;
3073 return RS2::Decimeter;
3076 return RS2::Decameter;
3079 return RS2::Hectometer;
3082 return RS2::Gigameter;
3088 return RS2::Lightyear;
3101 * Converst a unit enum into a DXF unit number e.g. for INSUNITS.
3103 int RS_FilterDXF::unitToNumber(RS2::Unit unit) {
3118 case RS2::Millimeter:
3121 case RS2::Centimeter:
3127 case RS2::Kilometer:
3130 case RS2::Microinch:
3142 case RS2::Nanometer:
3148 case RS2::Decimeter:
3151 case RS2::Decameter:
3154 case RS2::Hectometer:
3157 case RS2::Gigameter:
3163 case RS2::Lightyear:
3177 * Checks if the given variable is two-dimensional (e.g. $LIMMIN).
3179 bool RS_FilterDXF::isVariableTwoDimensional(const QString& var) {
3180 if (var=="$LIMMIN" ||