/**************************************************************************** ** Copyright (C) 2001-2013 RibbonSoft, GmbH. All rights reserved. ** ** This file is part of the dxflib project. ** ** This file is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** Licensees holding valid dxflib Professional Edition licenses may use ** this file in accordance with the dxflib Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.ribbonsoft.com for further details. ** ** Contact info@ribbonsoft.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "dl_dxf.h" #include #include #include #include #include #include "dl_attributes.h" #include "dl_codes.h" #include "dl_creationadapter.h" #include "dl_writer_ascii.h" #include "iostream" /** * Default constructor. */ DL_Dxf::DL_Dxf() : version(DL_VERSION_2000), polylineLayer(), vertices(nullptr), maxVertices(0), vertexIndex(0), knots(nullptr), maxKnots(0), knotIndex(0), weights(nullptr), weightIndex(0), controlPoints(nullptr), maxControlPoints(0), controlPointIndex(0), fitPoints(nullptr), maxFitPoints(0), fitPointIndex(0), leaderVertices(nullptr), maxLeaderVertices(0), leaderVertexIndex(0), firstHatchLoop(), hatchEdge(), hatchEdges(), xRecordHandle(), xRecordValues(), groupCodeTmp(), groupCode(), groupValue(), currentObjectType(), settingKey(), values(), firstCall(), attrib(), libVersion(), appDictionaryHandle(), styleHandleStd() { } /** * Destructor. */ DL_Dxf::~DL_Dxf() { if (vertices!=nullptr) { delete[] vertices; } if (knots!=nullptr) { delete[] knots; } if (controlPoints!=nullptr) { delete[] controlPoints; } if (fitPoints!=nullptr) { delete[] fitPoints; } if (weights!=nullptr) { delete[] weights; } if (leaderVertices!=nullptr) { delete[] leaderVertices; } } /** * @brief Reads the given file and calls the appropriate functions in * the given creation interface for every entity found in the file. * * @param file Input * Path and name of file to read * @param creationInterface * Pointer to the class which takes care of the entities in the file. * * @retval true If \p file could be opened. * @retval false If \p file could not be opened. */ bool DL_Dxf::in(const std::string& file, DL_CreationInterface* creationInterface) { FILE *fp; firstCall = true; currentObjectType = DL_UNKNOWN; fp = fopen(file.c_str(), "rt"); if (fp) { while (readDxfGroups(fp, creationInterface)) {} fclose(fp); return true; } return false; } /** * Reads a DXF file from an existing stream. * * @param stream The string stream. * @param creationInterface * Pointer to the class which takes care of the entities in the file. * * @retval true If \p file could be opened. * @retval false If \p file could not be opened. */ bool DL_Dxf::in(std::stringstream& stream, DL_CreationInterface* creationInterface) { if (stream.good()) { firstCall=true; currentObjectType = DL_UNKNOWN; while (readDxfGroups(stream, creationInterface)) {} return true; } return false; } /** * @brief Reads a group couplet from a DXF file. Calls another function * to process it. * * A group couplet consists of two lines that represent a single * piece of data. An integer constant on the first line indicates * the type of data. The value is on the next line.\n * * This function reads a couplet, determines the type of data, and * passes the value to the the appropriate handler function of * \p creationInterface.\n * * \p fp is advanced so that the next call to \p readDXFGroups() reads * the next couplet in the file. * * @param fp Handle of input file * @param creationInterface Handle of class which processes entities * in the file * * @retval true If EOF not reached. * @retval false If EOF reached. */ bool DL_Dxf::readDxfGroups(FILE *fp, DL_CreationInterface* creationInterface) { static int line = 1; // Read one group of the DXF file and strip the lines: if (DL_Dxf::getStrippedLine(groupCodeTmp, DL_DXF_MAXLINE, fp) && DL_Dxf::getStrippedLine(groupValue, DL_DXF_MAXLINE, fp) ) { groupCode = static_cast(toInt(groupCodeTmp)); creationInterface->processCodeValuePair(groupCode, groupValue); line+=2; processDXFGroup(creationInterface, groupCode, groupValue); } return !feof(fp); } /** * Same as above but for stringstreams. */ bool DL_Dxf::readDxfGroups(std::stringstream& stream, DL_CreationInterface* creationInterface) { static int line = 1; // Read one group of the DXF file and chop the lines: if (DL_Dxf::getStrippedLine(groupCodeTmp, DL_DXF_MAXLINE, stream) && DL_Dxf::getStrippedLine(groupValue, DL_DXF_MAXLINE, stream) ) { groupCode = static_cast(toInt(groupCodeTmp)); line+=2; processDXFGroup(creationInterface, groupCode, groupValue); } return !stream.eof(); } /** * @brief Reads line from file & strips whitespace at start and newline * at end. * * @param s Output\n * Pointer to character array that chopped line will be returned in. * @param size Size of \p s. (Including space for NULL.) * @param fp Input\n * Handle of input file. * * @retval true if line could be read * @retval false if \p fp is already at end of file * * @todo Change function to use safer FreeBSD strl* functions * @todo Is it a problem if line is blank (i.e., newline only)? * Then, when function returns, (s==NULL). */ bool DL_Dxf::getStrippedLine(std::string& s, unsigned int size, FILE *fp) { if (!feof(fp)) { // The whole line in the file. Includes space for NULL. char* wholeLine = new char[size]; // Only the useful part of the line char* line; line = fgets(wholeLine, size, fp); if (line!=NULL && line[0] != '\0') // Evaluates to fgets() retval { // line == wholeLine at this point. // Both guaranteed to be NULL terminated. // Strip leading whitespace and trailing CR/LF. stripWhiteSpace(&line); s = line; assert(size > s.length()); } delete[] wholeLine; // Done with wholeLine return true; } else { s = ""; return false; } } /** * Same as above but for stringstreams. */ bool DL_Dxf::getStrippedLine(std::string &s, unsigned int size, std::stringstream& stream) { if (!stream.eof()) { // Only the useful part of the line char* line = new char[size+1]; char* oriLine = line; stream.getline(line, size); stripWhiteSpace(&line); s = line; assert(size > s.length()); delete[] oriLine; return true; } else { s[0] = '\0'; return false; } } /** * @brief Strips leading whitespace and trailing Carriage Return (CR) * and Line Feed (LF) from NULL terminated string. * * @param s Input and output. * NULL terminates string. * * @retval true if \p s is non-NULL * @retval false if \p s is NULL */ bool DL_Dxf::stripWhiteSpace(char** s) { // last non-NULL char: int lastChar = static_cast(strlen(*s) - 1); // Is last character CR or LF? while ( (lastChar >= 0) && (((*s)[lastChar] == 10) || ((*s)[lastChar] == 13) || ((*s)[lastChar] == ' ' || ((*s)[lastChar] == '\t'))) ) { (*s)[lastChar] = '\0'; lastChar--; } // Skip whitespace, excluding \n, at beginning of line while ((*s)[0]==' ' || (*s)[0]=='\t') { ++(*s); } return ((*s) ? true : false); } /** * Processes a group (pair of group code and value). * * @param creationInterface Handle to class that creates entities and * other CAD data from DXF group codes * * @param groupCode Constant indicating the data type of the group. * @param groupValue The data value. * * @retval true if done processing current entity and new entity begun * @retval false if not done processing current entity */ bool DL_Dxf::processDXFGroup(DL_CreationInterface* creationInterface, int groupCode, const std::string& groupValue) { //printf("%d\n", groupCode); //printf("%s\n", groupValue.c_str()); // Init values on first call if (firstCall) { settingValue[0] = '\0'; firstCall=false; } // Indicates comment or dxflib version: if (groupCode==999) { if (!groupValue.empty()) { if (groupValue.substr(0, 6)=="dxflib") { libVersion = getLibVersion(groupValue.substr(7)); } addComment(creationInterface, groupValue); } } // Indicates start of new entity or variable: else if (groupCode==0 || groupCode==9) { // If new entity is encountered, the last one is complete. // Prepare default attributes for next entity: std::string layer = getStringValue(8, "0"); int width; // Compatibility with qcad1: if (hasValue(39) && !hasValue(370)) { width = getIntValue(39, -1); } // since autocad 2002: else if (hasValue(370)) { width = getIntValue(370, -1); } // default to BYLAYER: else { width = -1; } int color; color = getIntValue(62, 256); int color24; color24 = getIntValue(420, -1); int handle; handle = getIntValue(5, -1); std::string linetype = getStringValue(6, "BYLAYER"); attrib = DL_Attributes(layer, // layer color, // color color24, // 24 bit color width, // width linetype, // linetype handle); // handle attrib.setInPaperSpace(static_cast(getIntValue(67, 0))); attrib.setLinetypeScale(getRealValue(48, 1.0)); creationInterface->setAttributes(attrib); int elevationGroupCode=30; if (currentObjectType==DL_ENTITY_LWPOLYLINE ) { // see lwpolyline group codes reference elevationGroupCode=38; } else { // see polyline group codes reference elevationGroupCode=30; } creationInterface->setExtrusion(getRealValue(210, 0.0), getRealValue(220, 0.0), getRealValue(230, 1.0), getRealValue(elevationGroupCode, 0.0)); // Add the previously parsed entity via creationInterface switch (currentObjectType) { case DL_SETTING: addSetting(creationInterface); break; case DL_LAYER: addLayer(creationInterface); break; case DL_LINETYPE: addLinetype(creationInterface); break; case DL_BLOCK: addBlock(creationInterface); break; case DL_ENDBLK: endBlock(creationInterface); break; case DL_STYLE: addTextStyle(creationInterface); break; case DL_ENTITY_POINT: addPoint(creationInterface); break; case DL_ENTITY_LINE: addLine(creationInterface); break; case DL_ENTITY_XLINE: addXLine(creationInterface); break; case DL_ENTITY_RAY: addRay(creationInterface); break; case DL_ENTITY_POLYLINE: case DL_ENTITY_LWPOLYLINE: addPolyline(creationInterface); break; case DL_ENTITY_VERTEX: addVertex(creationInterface); break; case DL_ENTITY_SPLINE: addSpline(creationInterface); break; case DL_ENTITY_ARC: addArc(creationInterface); break; case DL_ENTITY_CIRCLE: addCircle(creationInterface); break; case DL_ENTITY_ELLIPSE: addEllipse(creationInterface); break; case DL_ENTITY_INSERT: addInsert(creationInterface); break; case DL_ENTITY_MTEXT: addMText(creationInterface); break; case DL_ENTITY_TEXT: addText(creationInterface); break; case DL_ENTITY_ATTRIB: addAttribute(creationInterface); break; case DL_ENTITY_DIMENSION: { int type = (getIntValue(70, 0)&0x07); switch (type) { case 0: addDimLinear(creationInterface); break; case 1: addDimAligned(creationInterface); break; case 2: addDimAngular(creationInterface); break; case 3: addDimDiametric(creationInterface); break; case 4: addDimRadial(creationInterface); break; case 5: addDimAngular3P(creationInterface); break; case 6: addDimOrdinate(creationInterface); break; default: break; } } break; case DL_ENTITY_LEADER: addLeader(creationInterface); break; case DL_ENTITY_HATCH: //addHatch(creationInterface); handleHatchData(creationInterface); break; case DL_ENTITY_IMAGE: addImage(creationInterface); break; case DL_ENTITY_IMAGEDEF: addImageDef(creationInterface); break; case DL_ENTITY_TRACE: addTrace(creationInterface); break; case DL_ENTITY_3DFACE: add3dFace(creationInterface); break; case DL_ENTITY_SOLID: addSolid(creationInterface); break; case DL_ENTITY_SEQEND: endSequence(creationInterface); break; default: break; } creationInterface->endSection(); // reset all values (they are not persistent and only this // way we can set defaults for omitted values) // for (int i=0; iaddComment(comment); } void DL_Dxf::addDictionary(DL_CreationInterface* creationInterface) { creationInterface->addDictionary(DL_DictionaryData(getStringValue(5, ""))); } void DL_Dxf::addDictionaryEntry(DL_CreationInterface* creationInterface) { creationInterface->addDictionaryEntry(DL_DictionaryEntryData(getStringValue(3, ""), getStringValue(350, ""))); } /** * Adds a variable from the DXF file. */ void DL_Dxf::addSetting(DL_CreationInterface* creationInterface) { int c = -1; std::map::iterator it = values.begin(); if (it!=values.end()) { c = it->first; } // for (int i=0; i<=380; ++i) { // if (values[i][0]!='\0') { // c = i; // break; // } // } // string if (c>=0 && c<=9) { creationInterface->setVariableString(settingKey, values[c], c); #ifdef DL_COMPAT // backwards compatibility: creationInterface->setVariableString(settingKey.c_str(), values[c].c_str(), c); #endif } // vector else if (c>=10 && c<=39) { if (c==10) { creationInterface->setVariableVector( settingKey, getRealValue(c, 0.0), getRealValue(c+10, 0.0), getRealValue(c+20, 0.0), c); } } // double else if (c>=40 && c<=59) { creationInterface->setVariableDouble(settingKey, getRealValue(c, 0.0), c); } // int else if (c>=60 && c<=99) { creationInterface->setVariableInt(settingKey, getIntValue(c, 0), c); } // misc else if (c>=0) { creationInterface->setVariableString(settingKey, getStringValue(c, ""), c); } } /** * Adds a layer that was read from the file via the creation interface. */ void DL_Dxf::addLayer(DL_CreationInterface* creationInterface) { // correct some invalid attributes for layers: attrib = creationInterface->getAttributes(); if (attrib.getColor()==256 || attrib.getColor()==0) { attrib.setColor(7); } if (attrib.getWidth()<0) { attrib.setWidth(1); } std::string linetype = attrib.getLinetype(); std::transform(linetype.begin(), linetype.end(), linetype.begin(), ::toupper); if (linetype=="BYLAYER" || linetype=="BYBLOCK") { attrib.setLinetype("CONTINUOUS"); } // add layer std::string name = getStringValue(2, ""); if (name.length()==0) { return; } creationInterface->addLayer(DL_LayerData(name, getIntValue(70, 0))); } /** * Adds a linetype that was read from the file via the creation interface. */ void DL_Dxf::addLinetype(DL_CreationInterface* creationInterface) { std::string name = getStringValue(2, ""); if (name.length()==0) { return; } int numDashes = getIntValue(73, 0); //double dashes[numDashes]; DL_LinetypeData d( // name: name, // description: getStringValue(3, ""), // flags getIntValue(70, 0), // number of dashes: numDashes, // pattern length: getRealValue(40, 0.0) // pattern: //dashes ); if (name != "By Layer" && name != "By Block" && name != "BYLAYER" && name != "BYBLOCK") { creationInterface->addLinetype(d); } } /** * Handles all dashes in linetype pattern. */ bool DL_Dxf::handleLinetypeData(DL_CreationInterface* creationInterface) { if (groupCode == 49) { creationInterface->addLinetypeDash(toReal(groupValue)); return true; } return false; } /** * Adds a block that was read from the file via the creation interface. */ void DL_Dxf::addBlock(DL_CreationInterface* creationInterface) { std::string name = getStringValue(2, ""); if (name.length()==0) { return; } DL_BlockData d( // Name: name, // flags: getIntValue(70, 0), // base point: getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0)); creationInterface->addBlock(d); } /** * Ends a block that was read from the file via the creation interface. */ void DL_Dxf::endBlock(DL_CreationInterface* creationInterface) { creationInterface->endBlock(); } void DL_Dxf::addTextStyle(DL_CreationInterface* creationInterface) { std::string name = getStringValue(2, ""); if (name.length()==0) { return; } DL_StyleData d( // name: name, // flags getIntValue(70, 0), // fixed text heigth: getRealValue(40, 0.0), // width factor: getRealValue(41, 0.0), // oblique angle: getRealValue(50, 0.0), // text generation flags: getIntValue(71, 0), // last height used: getRealValue(42, 0.0), // primart font file: getStringValue(3, ""), // big font file: getStringValue(4, "") ); creationInterface->addTextStyle(d); } /** * Adds a point entity that was read from the file via the creation interface. */ void DL_Dxf::addPoint(DL_CreationInterface* creationInterface) { DL_PointData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0)); creationInterface->addPoint(d); } /** * Adds a line entity that was read from the file via the creation interface. */ void DL_Dxf::addLine(DL_CreationInterface* creationInterface) { DL_LineData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0)); creationInterface->addLine(d); } /** * Adds an xline entity that was read from the file via the creation interface. */ void DL_Dxf::addXLine(DL_CreationInterface* creationInterface) { DL_XLineData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0)); creationInterface->addXLine(d); } /** * Adds a ray entity that was read from the file via the creation interface. */ void DL_Dxf::addRay(DL_CreationInterface* creationInterface) { DL_RayData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0)); creationInterface->addRay(d); } /** * Adds a polyline entity that was read from the file via the creation interface. */ void DL_Dxf::addPolyline(DL_CreationInterface* creationInterface) { DL_PolylineData pd(maxVertices, getIntValue(71, 0), getIntValue(72, 0), getIntValue(70, 0)); creationInterface->addPolyline(pd); maxVertices = std::min(maxVertices, vertexIndex+1); if (currentObjectType==DL_ENTITY_LWPOLYLINE) { for (int i=0; iaddVertex(d); } creationInterface->endEntity(); } } /** * Adds a polyline vertex entity that was read from the file * via the creation interface. */ void DL_Dxf::addVertex(DL_CreationInterface* creationInterface) { // vertex defines a face of the mesh if its vertex flags group has the // 128 bit set but not the 64 bit. 10, 20, 30 are irrelevant and set to // 0 in this case if ((getIntValue(70, 0)&128) && !(getIntValue(70, 0)&64)) { return; } DL_VertexData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(42, 0.0)); creationInterface->addVertex(d); } /** * Adds a spline entity that was read from the file via the creation interface. */ void DL_Dxf::addSpline(DL_CreationInterface* creationInterface) { DL_SplineData sd(getIntValue(71, 3), maxKnots, maxControlPoints, maxFitPoints, getIntValue(70, 4)); sd.tangentStartX = getRealValue(12, 0.0); sd.tangentStartY = getRealValue(22, 0.0); sd.tangentStartZ = getRealValue(32, 0.0); sd.tangentEndX = getRealValue(13, 0.0); sd.tangentEndY = getRealValue(23, 0.0); sd.tangentEndZ = getRealValue(33, 0.0); creationInterface->addSpline(sd); int i; for (i=0; iaddControlPoint(d); } for (i=0; iaddFitPoint(d); } for (i=0; iaddKnot(k); } creationInterface->endEntity(); } /** * Adds an arc entity that was read from the file via the creation interface. */ void DL_Dxf::addArc(DL_CreationInterface* creationInterface) { DL_ArcData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(40, 0.0), getRealValue(50, 0.0), getRealValue(51, 0.0)); creationInterface->addArc(d); } /** * Adds a circle entity that was read from the file via the creation interface. */ void DL_Dxf::addCircle(DL_CreationInterface* creationInterface) { DL_CircleData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(40, 0.0)); creationInterface->addCircle(d); } /** * Adds an ellipse entity that was read from the file via the creation interface. */ void DL_Dxf::addEllipse(DL_CreationInterface* creationInterface) { DL_EllipseData d(getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0), getRealValue(40, 1.0), getRealValue(41, 0.0), getRealValue(42, 2*M_PI)); creationInterface->addEllipse(d); } /** * Adds an insert entity that was read from the file via the creation interface. */ void DL_Dxf::addInsert(DL_CreationInterface* creationInterface) { //printf("addInsert\n"); //printf("code 50: %s\n", values[50]); //printf("code 50 length: %d\n", strlen(values[50])); //printf("code 50:\n"); //getRealValue(50, 0.0); std::string name = getStringValue(2, ""); if (name.length()==0) { return; } DL_InsertData d(name, // insertion point getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), // scale: getRealValue(41, 1.0), getRealValue(42, 1.0), getRealValue(43, 1.0), // angle (deg): getRealValue(50, 0.0), // cols / rows: getIntValue(70, 1), getIntValue(71, 1), // spacing: getRealValue(44, 0.0), getRealValue(45, 0.0)); creationInterface->addInsert(d); } /** * Adds a trace entity (4 edge closed polyline) that was read from the file via the creation interface. * * @author AHM */ void DL_Dxf::addTrace(DL_CreationInterface* creationInterface) { DL_TraceData td; for (int k = 0; k < 4; k++) { td.x[k] = getRealValue(10 + k, 0.0); td.y[k] = getRealValue(20 + k, 0.0); td.z[k] = getRealValue(30 + k, 0.0); } creationInterface->addTrace(td); } /** * Adds a 3dface entity that was read from the file via the creation interface. */ void DL_Dxf::add3dFace(DL_CreationInterface* creationInterface) { DL_3dFaceData td; for (int k = 0; k < 4; k++) { td.x[k] = getRealValue(10 + k, 0.0); td.y[k] = getRealValue(20 + k, 0.0); td.z[k] = getRealValue(30 + k, 0.0); } creationInterface->add3dFace(td); } /** * Adds a solid entity (filled trace) that was read from the file via the creation interface. * * @author AHM */ void DL_Dxf::addSolid(DL_CreationInterface* creationInterface) { DL_SolidData sd; for (int k = 0; k < 4; k++) { sd.x[k] = getRealValue(10 + k, 0.0); sd.y[k] = getRealValue(20 + k, 0.0); sd.z[k] = getRealValue(30 + k, 0.0); } creationInterface->addSolid(sd); } /** * Adds an MText entity that was read from the file via the creation interface. */ void DL_Dxf::addMText(DL_CreationInterface* creationInterface) { double angle = 0.0; if (hasValue(50)) { if (libVersion<=0x02000200) { // wrong but compatible with dxflib <=2.0.2.0: angle = getRealValue(50, 0.0); } else { angle = (getRealValue(50, 0.0)*2*M_PI)/360.0; } } else if (hasValue(11) && hasValue(21)) { double x = getRealValue(11, 0.0); double y = getRealValue(21, 0.0); if (fabs(x)<1.0e-6) { if (y>0.0) { angle = M_PI/2.0; } else { angle = M_PI/2.0*3.0; } } else { angle = atan(y/x); } } DL_MTextData d( // insertion point getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), // X direction vector getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0), // height getRealValue(40, 2.5), // width getRealValue(41, 0.0), // attachment point getIntValue(71, 1), // drawing direction getIntValue(72, 1), // line spacing style getIntValue(73, 1), // line spacing factor getRealValue(44, 1.0), // text getStringValue(1, ""), // style getStringValue(7, ""), // angle angle); creationInterface->addMText(d); } /** * Handles all XRecord data. */ bool DL_Dxf::handleXRecordData(DL_CreationInterface* creationInterface) { if (groupCode==105) { return false; } if (groupCode==5) { creationInterface->addXRecord(groupValue); return true; } if (groupCode==280) { xRecordValues = true; return true; } if (!xRecordValues) { return false; } // string: if (groupCode<=9 || groupCode==100 || groupCode==102 || groupCode==105 || (groupCode>=300 && groupCode<=369) || (groupCode>=1000 && groupCode<=1009)) { creationInterface->addXRecordString(groupCode, groupValue); return true; } // int: else if ((groupCode>=60 && groupCode<=99) || (groupCode>=160 && groupCode<=179) || (groupCode>=270 && groupCode<=289)) { creationInterface->addXRecordInt(groupCode, toInt(groupValue)); return true; } // bool: else if (groupCode>=290 && groupCode<=299) { creationInterface->addXRecordBool(groupCode, toBool(groupValue)); return true; } // double: else if ((groupCode>=10 && groupCode<=59) || (groupCode>=110 && groupCode<=149) || (groupCode>=210 && groupCode<=239)) { creationInterface->addXRecordReal(groupCode, toReal(groupValue)); return true; } return false; } /** * Handles all dictionary data. */ bool DL_Dxf::handleDictionaryData(DL_CreationInterface* creationInterface) { if (groupCode==3) { return true; } if (groupCode==5) { creationInterface->addDictionary(DL_DictionaryData(groupValue)); return true; } if (groupCode==350) { creationInterface->addDictionaryEntry(DL_DictionaryEntryData(getStringValue(3, ""), groupValue)); return true; } return false; } /** * Handles XData for all object types. */ bool DL_Dxf::handleXData(DL_CreationInterface* creationInterface) { if (groupCode==1001) { creationInterface->addXDataApp(groupValue); return true; } else if (groupCode>=1000 && groupCode<=1009) { creationInterface->addXDataString(groupCode, groupValue); return true; } else if (groupCode>=1010 && groupCode<=1059) { creationInterface->addXDataReal(groupCode, toReal(groupValue)); return true; } else if (groupCode>=1060 && groupCode<=1070) { creationInterface->addXDataInt(groupCode, toInt(groupValue)); return true; } else if (groupCode==1071) { creationInterface->addXDataInt(groupCode, toInt(groupValue)); return true; } return false; } /** * Handles additional MText data. */ bool DL_Dxf::handleMTextData(DL_CreationInterface* creationInterface) { // Special handling of text chunks for MTEXT entities: if (groupCode==3) { creationInterface->addMTextChunk(groupValue); return true; } return false; } /** * Handles additional polyline data. */ bool DL_Dxf::handleLWPolylineData(DL_CreationInterface* /*creationInterface*/) { // Allocate LWPolyline vertices (group code 90): if (groupCode==90) { maxVertices = toInt(groupValue); if (maxVertices>0) { if (vertices!=nullptr) { delete[] vertices; } vertices = new double[4*maxVertices]; for (int i=0; i=0 && vertexIndex0) { if (knots!=nullptr) { delete[] knots; } knots = new double[maxKnots]; for (int i=0; i0) { if (controlPoints!=nullptr) { delete[] controlPoints; } if (weights!=nullptr) { delete[] weights; } controlPoints = new double[3*maxControlPoints]; weights = new double[maxControlPoints]; for (int i=0; i0) { if (fitPoints!=nullptr) { delete[] fitPoints; } fitPoints = new double[3*maxFitPoints]; for (int i=0; i=0 && controlPointIndex=0 && fitPointIndex=0 && weightIndex0) { if (leaderVertices!=nullptr) { delete[] leaderVertices; } leaderVertices = new double[3*maxLeaderVertices]; for (int i=0; i=0 && leaderVertexIndexaddText(d); } /** * Adds an attrib entity that was read from the file via the creation interface. * @todo add attrib instead of normal text */ void DL_Dxf::addAttribute(DL_CreationInterface* creationInterface) { DL_AttributeData d( // insertion point getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), // alignment point getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0), // height getRealValue(40, 2.5), // x scale getRealValue(41, 1.0), // generation flags getIntValue(71, 0), // h just getIntValue(72, 0), // v just getIntValue(74, 0), // tag getStringValue(2, ""), // text getStringValue(1, ""), // style getStringValue(7, ""), // angle (getRealValue(50, 0.0)*2*M_PI)/360.0); creationInterface->addAttribute(d); } /** * @return dimension data from current values. */ DL_DimensionData DL_Dxf::getDimData() { // generic dimension data: return DL_DimensionData( // def point getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), // text middle point getRealValue(11, 0.0), getRealValue(21, 0.0), getRealValue(31, 0.0), // type getIntValue(70, 0), // attachment point getIntValue(71, 5), // line sp. style getIntValue(72, 1), // line sp. factor getRealValue(41, 1.0), // text getStringValue(1, ""), // style getStringValue(3, ""), // angle getRealValue(53, 0.0)); } /** * Adds a linear dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimLinear(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // horizontal / vertical / rotated dimension: DL_DimLinearData dl( // definition point 1 getRealValue(13, 0.0), getRealValue(23, 0.0), getRealValue(33, 0.0), // definition point 2 getRealValue(14, 0.0), getRealValue(24, 0.0), getRealValue(34, 0.0), // angle getRealValue(50, 0.0), // oblique getRealValue(52, 0.0)); creationInterface->addDimLinear(d, dl); } /** * Adds an aligned dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimAligned(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // aligned dimension: DL_DimAlignedData da( // extension point 1 getRealValue(13, 0.0), getRealValue(23, 0.0), getRealValue(33, 0.0), // extension point 2 getRealValue(14, 0.0), getRealValue(24, 0.0), getRealValue(34, 0.0)); creationInterface->addDimAlign(d, da); } /** * Adds a radial dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimRadial(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); DL_DimRadialData dr( // definition point getRealValue(15, 0.0), getRealValue(25, 0.0), getRealValue(35, 0.0), // leader length: getRealValue(40, 0.0)); creationInterface->addDimRadial(d, dr); } /** * Adds a diametric dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimDiametric(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // diametric dimension: DL_DimDiametricData dr( // definition point getRealValue(15, 0.0), getRealValue(25, 0.0), getRealValue(35, 0.0), // leader length: getRealValue(40, 0.0)); creationInterface->addDimDiametric(d, dr); } /** * Adds an angular dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimAngular(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // angular dimension: DL_DimAngularData da( // definition point 1 getRealValue(13, 0.0), getRealValue(23, 0.0), getRealValue(33, 0.0), // definition point 2 getRealValue(14, 0.0), getRealValue(24, 0.0), getRealValue(34, 0.0), // definition point 3 getRealValue(15, 0.0), getRealValue(25, 0.0), getRealValue(35, 0.0), // definition point 4 getRealValue(16, 0.0), getRealValue(26, 0.0), getRealValue(36, 0.0)); creationInterface->addDimAngular(d, da); } /** * Adds an angular dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimAngular3P(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // angular dimension (3P): DL_DimAngular3PData da( // definition point 1 getRealValue(13, 0.0), getRealValue(23, 0.0), getRealValue(33, 0.0), // definition point 2 getRealValue(14, 0.0), getRealValue(24, 0.0), getRealValue(34, 0.0), // definition point 3 getRealValue(15, 0.0), getRealValue(25, 0.0), getRealValue(35, 0.0)); creationInterface->addDimAngular3P(d, da); } /** * Adds an ordinate dimension entity that was read from the file via the creation interface. */ void DL_Dxf::addDimOrdinate(DL_CreationInterface* creationInterface) { DL_DimensionData d = getDimData(); // ordinate dimension: DL_DimOrdinateData dl( // definition point 1 getRealValue(13, 0.0), getRealValue(23, 0.0), getRealValue(33, 0.0), // definition point 2 getRealValue(14, 0.0), getRealValue(24, 0.0), getRealValue(34, 0.0), (getIntValue(70, 0)&64)==64 // true: X-type, false: Y-type ); creationInterface->addDimOrdinate(d, dl); } /** * Adds a leader entity that was read from the file via the creation interface. */ void DL_Dxf::addLeader(DL_CreationInterface* creationInterface) { // leader (arrow) DL_LeaderData le( // arrow head flag getIntValue(71, 1), // leader path type getIntValue(72, 0), // Leader creation flag getIntValue(73, 3), // Hookline direction flag getIntValue(74, 1), // Hookline flag getIntValue(75, 0), // Text annotation height getRealValue(40, 1.0), // Text annotation width getRealValue(41, 1.0), // Number of vertices in leader getIntValue(76, 0) ); creationInterface->addLeader(le); for (int i=0; iaddLeaderVertex(d); } creationInterface->endEntity(); } /** * Adds a hatch entity that was read from the file via the creation interface. */ void DL_Dxf::addHatch(DL_CreationInterface* creationInterface) { DL_HatchData hd(getIntValue(91, 1), getIntValue(70, 0), getRealValue(41, 1.0), getRealValue(52, 0.0), getStringValue(2, "")); creationInterface->addHatch(hd); for (unsigned int i=0; iaddHatchLoop(DL_HatchLoopData(static_cast(hatchEdges[i].size()))); for (unsigned int k=0; kaddHatchEdge(DL_HatchEdgeData(hatchEdges[i][k])); } } creationInterface->endEntity(); } void DL_Dxf::addHatchLoop() { addHatchEdge(); hatchEdges.push_back(std::vector()); } void DL_Dxf::addHatchEdge() { if (hatchEdge.defined) { if (hatchEdges.size()>0) { hatchEdges.back().push_back(hatchEdge); } hatchEdge = DL_HatchEdgeData(); } } /** * Handles all hatch data. */ bool DL_Dxf::handleHatchData(DL_CreationInterface* creationInterface) { // New polyline loop, group code 92 // or new loop with individual edges, group code 93 if (groupCode==92 || groupCode==93) { if (firstHatchLoop) { hatchEdges.clear(); firstHatchLoop = false; } if (groupCode==92 && (toInt(groupValue)&2)==2) { addHatchLoop(); } if (groupCode==93) { addHatchLoop(); } return true; } // New hatch edge or new section / entity: add last hatch edge: if (groupCode==72 || groupCode==0 || groupCode==78 || groupCode==98) { // polyline boundaries use code 72 for bulge flag: if (groupCode!=72 || (getIntValue(92, 0)&2)==0) { addHatchEdge(); } if (groupCode==0 /*|| groupCode==78*/) { addHatch(creationInterface); } else { hatchEdge.type = toInt(groupValue); } return true; } // polyline boundary: if ((getIntValue(92, 0)&2)==2) { switch (groupCode) { case 10: hatchEdge.type = 0; hatchEdge.vertices.push_back(std::vector()); hatchEdge.vertices.back().push_back(toReal(groupValue)); return true; case 20: if (!hatchEdge.vertices.empty()) { hatchEdge.vertices.back().push_back(toReal(groupValue)); hatchEdge.defined = true; } return true; case 42: if (!hatchEdge.vertices.empty()) { hatchEdge.vertices.back().push_back(toReal(groupValue)); hatchEdge.defined = true; } return true; default: return false; } } else { // Line edge: if (hatchEdge.type==1) { switch (groupCode) { case 10: hatchEdge.x1 = toReal(groupValue); return true; case 20: hatchEdge.y1 = toReal(groupValue); return true; case 11: hatchEdge.x2 = toReal(groupValue); return true; case 21: hatchEdge.y2 = toReal(groupValue); hatchEdge.defined = true; return true; default: return false; } } // Arc edge: if (hatchEdge.type==2) { switch(groupCode) { case 10: hatchEdge.cx = toReal(groupValue); return true; case 20: hatchEdge.cy = toReal(groupValue); return true; case 40: hatchEdge.radius = toReal(groupValue); return true; case 50: hatchEdge.angle1 = toReal(groupValue)/360.0*2*M_PI; return true; case 51: hatchEdge.angle2 = toReal(groupValue)/360.0*2*M_PI; return true; case 73: hatchEdge.ccw = static_cast(toInt(groupValue)); hatchEdge.defined = true; return true; default: return false; } } // Ellipse arc edge: if (hatchEdge.type==3) { switch (groupCode) { case 10: hatchEdge.cx = toReal(groupValue); return true; case 20: hatchEdge.cy = toReal(groupValue); return true; case 11: hatchEdge.mx = toReal(groupValue); return true; case 21: hatchEdge.my = toReal(groupValue); return true; case 40: hatchEdge.ratio = toReal(groupValue); return true; case 50: hatchEdge.angle1 = toReal(groupValue)/360.0*2*M_PI; return true; case 51: hatchEdge.angle2 = toReal(groupValue)/360.0*2*M_PI; return true; case 73: hatchEdge.ccw = static_cast(toInt(groupValue)); hatchEdge.defined = true; return true; default: return false; } } // Spline edge: if (hatchEdge.type==4) { switch (groupCode) { case 94: hatchEdge.degree = toInt(groupValue); return true; case 73: hatchEdge.rational = toBool(groupValue); return true; case 74: hatchEdge.periodic = toBool(groupValue); return true; case 95: hatchEdge.nKnots = toInt(groupValue); return true; case 96: hatchEdge.nControl = toInt(groupValue); return true; case 97: hatchEdge.nFit = toInt(groupValue); return true; case 40: if (hatchEdge.knots.size() < hatchEdge.nKnots) { hatchEdge.knots.push_back(toReal(groupValue)); } return true; case 10: if (hatchEdge.controlPoints.size() < hatchEdge.nControl) { std::vector v; v.push_back(toReal(groupValue)); hatchEdge.controlPoints.push_back(v); } return true; case 20: if (!hatchEdge.controlPoints.empty() && hatchEdge.controlPoints.back().size()==1) { hatchEdge.controlPoints.back().push_back(toReal(groupValue)); } hatchEdge.defined = true; return true; case 42: if (hatchEdge.weights.size() < hatchEdge.nControl) { hatchEdge.weights.push_back(toReal(groupValue)); } return true; case 11: if (hatchEdge.fitPoints.size() < hatchEdge.nFit) { std::vector v; v.push_back(toReal(groupValue)); hatchEdge.fitPoints.push_back(v); } return true; case 21: if (!hatchEdge.fitPoints.empty() && hatchEdge.fitPoints.back().size()==1) { hatchEdge.fitPoints.back().push_back(toReal(groupValue)); } hatchEdge.defined = true; return true; case 12: hatchEdge.startTangentX = toReal(groupValue); return true; case 22: hatchEdge.startTangentY = toReal(groupValue); return true; case 13: hatchEdge.endTangentX = toReal(groupValue); return true; case 23: hatchEdge.endTangentY = toReal(groupValue); return true; default: return false; } } } return false; } /** * Adds an image entity that was read from the file via the creation interface. */ void DL_Dxf::addImage(DL_CreationInterface* creationInterface) { DL_ImageData id(// pass ref insead of name we don't have yet getStringValue(340, ""), // ins point: getRealValue(10, 0.0), getRealValue(20, 0.0), getRealValue(30, 0.0), // u vector: getRealValue(11, 1.0), getRealValue(21, 0.0), getRealValue(31, 0.0), // v vector: getRealValue(12, 0.0), getRealValue(22, 1.0), getRealValue(32, 0.0), // image size (pixel): getIntValue(13, 1), getIntValue(23, 1), // brightness, contrast, fade getIntValue(281, 50), getIntValue(282, 50), getIntValue(283, 0)); creationInterface->addImage(id); creationInterface->endEntity(); currentObjectType = DL_UNKNOWN; } /** * Adds an image definition that was read from the file via the creation interface. */ void DL_Dxf::addImageDef(DL_CreationInterface* creationInterface) { DL_ImageDefData id(// handle getStringValue(5, ""), getStringValue(1, "")); creationInterface->linkImage(id); creationInterface->endEntity(); currentObjectType = DL_UNKNOWN; } /** * Ends some special entities like hatches or old style polylines. */ void DL_Dxf::endEntity(DL_CreationInterface* creationInterface) { creationInterface->endEntity(); } /** * Ends a sequence and notifies the creation interface. */ void DL_Dxf::endSequence(DL_CreationInterface* creationInterface) { creationInterface->endSequence(); } /** * Converts the given string into an int. * ok is set to false if there was an error. */ //int DL_Dxf::stringToInt(const char* s, bool* ok) { // if (ok!=NULL) { // // check string: // *ok = true; // int i=0; // bool dot = false; // do { // if (s[i]=='\0') { // break; // } else if (s[i]=='.') { // if (dot==true) { // //std::cerr << "two dots\n"; // *ok = false; // } else { // dot = true; // } // } else if (s[i]<'0' || s[i]>'9') { // //std::cerr << "NaN: '" << s[i] << "'\n"; // *ok = false; // } // i++; // } while(s[i]!='\0' && *ok==true); // } // return atoi(s); //} /** * @brief Opens the given file for writing and returns a pointer * to the dxf writer. This pointer needs to be passed on to other * writing functions. * * @param file Full path of the file to open. * * @return Pointer to an ascii dxf writer object. */ DL_WriterA* DL_Dxf::out(const char* file, DL_Codes::version version) { char* f = new char[strlen(file)+1]; strcpy(f, file); this->version = version; DL_WriterA* dw = new DL_WriterA(f, version); if (dw->openFailed()) { delete dw; delete[] f; return NULL; } else { delete[] f; return dw; } } /** * @brief Writes a DXF header to the file currently opened * by the given DXF writer object. */ void DL_Dxf::writeHeader(DL_WriterA& dw) { dw.comment("dxflib " DL_VERSION); dw.sectionHeader(); dw.dxfString(9, "$ACADVER"); switch (version) { case DL_Codes::AC1009: dw.dxfString(1, "AC1009"); break; case DL_Codes::AC1012: dw.dxfString(1, "AC1012"); break; case DL_Codes::AC1014: dw.dxfString(1, "AC1014"); break; case DL_Codes::AC1015: dw.dxfString(1, "AC1015"); break; default: break; } // Newer version require that (otherwise a*cad crashes..) if (version==DL_VERSION_2000) { dw.dxfString(9, "$HANDSEED"); dw.dxfHex(5, 0xFFFF); } // commented out: more variables can be added after that by caller: //dw.sectionEnd(); } /** * Writes a point entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writePoint(DL_WriterA& dw, const DL_PointData& data, const DL_Attributes& attrib) { dw.entity("POINT"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbPoint"); } dw.entityAttributes(attrib); dw.coord(DL_POINT_COORD_CODE, data.x, data.y, data.z); } /** * Writes a line entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeLine(DL_WriterA& dw, const DL_LineData& data, const DL_Attributes& attrib) { dw.entity("LINE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbLine"); } dw.entityAttributes(attrib); dw.coord(DL_LINE_START_CODE, data.x1, data.y1, data.z1); dw.coord(DL_LINE_END_CODE, data.x2, data.y2, data.z2); } /** * Writes an x line entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeXLine(DL_WriterA& dw, const DL_XLineData& data, const DL_Attributes& attrib) { dw.entity("XLINE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbLine"); } dw.entityAttributes(attrib); dw.coord(DL_LINE_START_CODE, data.bx, data.by, data.bz); dw.coord(DL_LINE_END_CODE, data.dx, data.dy, data.dz); } /** * Writes a ray entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeRay(DL_WriterA& dw, const DL_RayData& data, const DL_Attributes& attrib) { dw.entity("RAY"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbLine"); } dw.entityAttributes(attrib); dw.coord(DL_LINE_START_CODE, data.bx, data.by, data.bz); dw.coord(DL_LINE_END_CODE, data.dx, data.dy, data.dz); } /** * Writes a polyline entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes * @see writeVertex */ void DL_Dxf::writePolyline(DL_WriterA& dw, const DL_PolylineData& data, const DL_Attributes& attrib) { if (version==DL_VERSION_2000) { dw.entity("LWPOLYLINE"); dw.entityAttributes(attrib); dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbPolyline"); dw.dxfInt(90, static_cast(data.number)); dw.dxfInt(70, data.flags); } else { dw.entity("POLYLINE"); dw.entityAttributes(attrib); polylineLayer = attrib.getLayer(); dw.dxfInt(66, 1); dw.dxfInt(70, data.flags); dw.coord(DL_VERTEX_COORD_CODE, 0.0, 0.0, 0.0); } } /** * Writes a single vertex of a polyline to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeVertex(DL_WriterA& dw, const DL_VertexData& data) { if (version==DL_VERSION_2000) { dw.dxfReal(10, data.x); dw.dxfReal(20, data.y); dw.dxfReal(30, data.z); if (fabs(data.bulge)>1.0e-10) { dw.dxfReal(42, data.bulge); } } else { dw.entity("VERTEX"); //dw.entityAttributes(attrib); dw.dxfString(8, polylineLayer); dw.coord(DL_VERTEX_COORD_CODE, data.x, data.y, data.z); if (fabs(data.bulge)>1.0e-10) { dw.dxfReal(42, data.bulge); } } } /** * Writes the polyline end. Only needed for DXF R12. */ void DL_Dxf::writePolylineEnd(DL_WriterA& dw) { if (version==DL_VERSION_2000) { } else { dw.entity("SEQEND"); } } /** * Writes a spline entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes * @see writeControlPoint */ void DL_Dxf::writeSpline(DL_WriterA& dw, const DL_SplineData& data, const DL_Attributes& attrib) { dw.entity("SPLINE"); dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbSpline"); } dw.dxfInt(70, data.flags); dw.dxfInt(71, data.degree); dw.dxfInt(72, data.nKnots); // number of knots dw.dxfInt(73, data.nControl); // number of control points dw.dxfInt(74, data.nFit); // number of fit points } /** * Writes a single control point of a spline to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeControlPoint(DL_WriterA& dw, const DL_ControlPointData& data) { dw.dxfReal(10, data.x); dw.dxfReal(20, data.y); dw.dxfReal(30, data.z); } /** * Writes a single fit point of a spline to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeFitPoint(DL_WriterA& dw, const DL_FitPointData& data) { dw.dxfReal(11, data.x); dw.dxfReal(21, data.y); dw.dxfReal(31, data.z); } /** * Writes a single knot of a spline to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeKnot(DL_WriterA& dw, const DL_KnotData& data) { dw.dxfReal(40, data.k); } /** * Writes a circle entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeCircle(DL_WriterA& dw, const DL_CircleData& data, const DL_Attributes& attrib) { dw.entity("CIRCLE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbCircle"); } dw.entityAttributes(attrib); dw.coord(10, data.cx, data.cy, data.cz); dw.dxfReal(40, data.radius); } /** * Writes an arc entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeArc(DL_WriterA& dw, const DL_ArcData& data, const DL_Attributes& attrib) { dw.entity("ARC"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbCircle"); } dw.coord(10, data.cx, data.cy, data.cz); dw.dxfReal(40, data.radius); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbArc"); } dw.dxfReal(50, data.angle1); dw.dxfReal(51, data.angle2); } /** * Writes an ellipse entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeEllipse(DL_WriterA& dw, const DL_EllipseData& data, const DL_Attributes& attrib) { if (version>DL_VERSION_R12) { dw.entity("ELLIPSE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbEllipse"); } dw.entityAttributes(attrib); dw.coord(10, data.cx, data.cy, data.cz); dw.coord(11, data.mx, data.my, data.mz); dw.dxfReal(40, data.ratio); dw.dxfReal(41, data.angle1); dw.dxfReal(42, data.angle2); } } /** * Writes a solid entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeSolid(DL_WriterA& dw, const DL_SolidData& data, const DL_Attributes& attrib) { dw.entity("SOLID"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbTrace"); } dw.entityAttributes(attrib); dw.coord(10, data.x[0], data.y[0], data.z[0]); dw.coord(11, data.x[1], data.y[1], data.z[1]); dw.coord(12, data.x[2], data.y[2], data.z[2]); dw.coord(13, data.x[3], data.y[3], data.z[3]); dw.dxfReal(39, data.thickness); } /** * Writes a trace entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeTrace(DL_WriterA& dw, const DL_TraceData& data, const DL_Attributes& attrib) { dw.entity("TRACE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbTrace"); } dw.entityAttributes(attrib); dw.coord(10, data.x[0], data.y[0], data.z[0]); dw.coord(11, data.x[1], data.y[1], data.z[1]); dw.coord(12, data.x[2], data.y[2], data.z[2]); dw.coord(13, data.x[3], data.y[3], data.z[3]); dw.dxfReal(39, data.thickness); } /** * Writes a 3d face entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::write3dFace(DL_WriterA& dw, const DL_3dFaceData& data, const DL_Attributes& attrib) { dw.entity("3DFACE"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbFace"); } dw.entityAttributes(attrib); dw.coord(10, data.x[0], data.y[0], data.z[0]); dw.coord(11, data.x[1], data.y[1], data.z[1]); dw.coord(12, data.x[2], data.y[2], data.z[2]); dw.coord(13, data.x[3], data.y[3], data.z[3]); } /** * Writes an insert to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeInsert(DL_WriterA& dw, const DL_InsertData& data, const DL_Attributes& attrib) { if (data.name.empty()) { std::cerr << "DL_Dxf::writeInsert: " << "Block name must not be empty\n"; return; } dw.entity("INSERT"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbBlockReference"); } dw.entityAttributes(attrib); dw.dxfString(2, data.name); dw.dxfReal(10, data.ipx); dw.dxfReal(20, data.ipy); dw.dxfReal(30, data.ipz); if (!DL_FuzzyComparePossibleNulls(data.sx, 1.0) || !DL_FuzzyComparePossibleNulls(data.sy, 1.0)) { dw.dxfReal(41, data.sx); dw.dxfReal(42, data.sy); dw.dxfReal(43, 1.0); } if (!DL_FuzzyComparePossibleNulls(data.angle, 0.0)) { dw.dxfReal(50, data.angle); } if (data.cols!=1 || data.rows!=1) { dw.dxfInt(70, data.cols); dw.dxfInt(71, data.rows); } if (!DL_FuzzyComparePossibleNulls(data.colSp, 0.0) || !DL_FuzzyComparePossibleNulls(data.rowSp, 0.0)) { dw.dxfReal(44, data.colSp); dw.dxfReal(45, data.rowSp); } } /** * Writes a multi text entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeMText(DL_WriterA& dw, const DL_MTextData& data, const DL_Attributes& attrib) { dw.entity("MTEXT"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbMText"); } dw.entityAttributes(attrib); dw.dxfReal(10, data.ipx); dw.dxfReal(20, data.ipy); dw.dxfReal(30, data.ipz); dw.dxfReal(40, data.height); dw.dxfReal(41, data.width); dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.drawingDirection); // Creare text chunks of 250 characters each: int length = static_cast(data.text.length()); char chunk[251]; int i; for (i=250; i(data.linearFactor)); dw.dxfString(1002, "}"); } } /** * Writes an aligned dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific aligned dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimAligned(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAlignedData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbAlignedDimension"); } dw.dxfReal(13, edata.epx1); dw.dxfReal(23, edata.epy1); dw.dxfReal(33, 0.0); dw.dxfReal(14, edata.epx2); dw.dxfReal(24, edata.epy2); dw.dxfReal(34, 0.0); writeDimStyleOverrides(dw, data); } /** * Writes a linear dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific linear dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimLinear(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimLinearData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbAlignedDimension"); } dw.dxfReal(13, edata.dpx1); dw.dxfReal(23, edata.dpy1); dw.dxfReal(33, 0.0); dw.dxfReal(14, edata.dpx2); dw.dxfReal(24, edata.dpy2); dw.dxfReal(34, 0.0); dw.dxfReal(50, edata.angle/(2.0*M_PI)*360.0); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbRotatedDimension"); } writeDimStyleOverrides(dw, data); } /** * Writes a radial dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific radial dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimRadial(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimRadialData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbRadialDimension"); } dw.dxfReal(15, edata.dpx); dw.dxfReal(25, edata.dpy); dw.dxfReal(35, 0.0); dw.dxfReal(40, edata.leader); writeDimStyleOverrides(dw, data); } /** * Writes a diametric dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific diametric dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimDiametric(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimDiametricData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDiametricDimension"); } dw.dxfReal(15, edata.dpx); dw.dxfReal(25, edata.dpy); dw.dxfReal(35, 0.0); dw.dxfReal(40, edata.leader); writeDimStyleOverrides(dw, data); } /** * Writes an angular dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific angular dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimAngular(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAngularData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDb2LineAngularDimension"); } dw.dxfReal(13, edata.dpx1); dw.dxfReal(23, edata.dpy1); dw.dxfReal(33, 0.0); dw.dxfReal(14, edata.dpx2); dw.dxfReal(24, edata.dpy2); dw.dxfReal(34, 0.0); dw.dxfReal(15, edata.dpx3); dw.dxfReal(25, edata.dpy3); dw.dxfReal(35, 0.0); dw.dxfReal(16, edata.dpx4); dw.dxfReal(26, edata.dpy4); dw.dxfReal(36, 0.0); } /** * Writes an angular dimension entity (3 points version) to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific angular dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimAngular3P(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAngular3PData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); dw.dxfInt(70, data.type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfReal(42, data.angle); dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDb3PointAngularDimension"); } dw.dxfReal(13, edata.dpx1); dw.dxfReal(23, edata.dpy1); dw.dxfReal(33, 0.0); dw.dxfReal(14, edata.dpx2); dw.dxfReal(24, edata.dpy2); dw.dxfReal(34, 0.0); dw.dxfReal(15, edata.dpx3); dw.dxfReal(25, edata.dpy3); dw.dxfReal(35, 0.0); } /** * Writes an ordinate dimension entity to the file. * * @param dw DXF writer * @param data Generic dimension data for from the file * @param data Specific ordinate dimension data from the file * @param attrib Attributes */ void DL_Dxf::writeDimOrdinate(DL_WriterA& dw, const DL_DimensionData& data, const DL_DimOrdinateData& edata, const DL_Attributes& attrib) { dw.entity("DIMENSION"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); } dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimension"); } dw.dxfReal(10, data.dpx); dw.dxfReal(20, data.dpy); dw.dxfReal(30, data.dpz); dw.dxfReal(11, data.mpx); dw.dxfReal(21, data.mpy); dw.dxfReal(31, 0.0); int type = data.type; if (edata.xtype) { type|=0x40; } dw.dxfInt(70, type); if (version>DL_VERSION_R12) { dw.dxfInt(71, data.attachmentPoint); dw.dxfInt(72, data.lineSpacingStyle); // opt dw.dxfReal(41, data.lineSpacingFactor); // opt } dw.dxfString(1, data.text); // opt //dw.dxfString(3, data.style); dw.dxfString(3, "Standard"); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbOrdinateDimension"); } dw.dxfReal(13, edata.dpx1); dw.dxfReal(23, edata.dpy1); dw.dxfReal(33, 0.0); dw.dxfReal(14, edata.dpx2); dw.dxfReal(24, edata.dpy2); dw.dxfReal(34, 0.0); } /** * Writes a leader entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes * @see writeVertex */ void DL_Dxf::writeLeader(DL_WriterA& dw, const DL_LeaderData& data, const DL_Attributes& attrib) { if (version>DL_VERSION_R12) { dw.entity("LEADER"); dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbLeader"); } dw.dxfString(3, "Standard"); dw.dxfInt(71, data.arrowHeadFlag); dw.dxfInt(72, data.leaderPathType); dw.dxfInt(73, data.leaderCreationFlag); dw.dxfInt(74, data.hooklineDirectionFlag); dw.dxfInt(75, data.hooklineFlag); dw.dxfReal(40, data.textAnnotationHeight); dw.dxfReal(41, data.textAnnotationWidth); dw.dxfInt(76, data.number); } } /** * Writes a single vertex of a leader to the file. * * @param dw DXF writer * @param data Entity data */ void DL_Dxf::writeLeaderVertex(DL_WriterA& dw, const DL_LeaderVertexData& data) { if (version>DL_VERSION_R12) { dw.dxfReal(10, data.x); dw.dxfReal(20, data.y); } } /** * Writes the beginning of a hatch entity to the file. * This must be followed by one or more writeHatchLoop() * calls and a writeHatch2() call. * * @param dw DXF writer * @param data Entity data. * @param attrib Attributes */ void DL_Dxf::writeHatch1(DL_WriterA& dw, const DL_HatchData& data, const DL_Attributes& attrib) { dw.entity("HATCH"); dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbHatch"); } dw.dxfReal(10, 0.0); // elevation dw.dxfReal(20, 0.0); dw.dxfReal(30, 0.0); dw.dxfReal(210, 0.0); // extrusion dir. dw.dxfReal(220, 0.0); dw.dxfReal(230, 1.0); if (data.solid==false) { dw.dxfString(2, data.pattern); } else { dw.dxfString(2, "SOLID"); } dw.dxfInt(70, static_cast(data.solid)); dw.dxfInt(71, 0); // non-associative dw.dxfInt(91, data.numLoops); } /** * Writes the end of a hatch entity to the file. * * @param dw DXF writer * @param data Entity data. * @param attrib Attributes */ void DL_Dxf::writeHatch2(DL_WriterA& dw, const DL_HatchData& data, const DL_Attributes& /*attrib*/) { dw.dxfInt(75, 0); // odd parity dw.dxfInt(76, 1); // pattern type if (data.solid==false) { dw.dxfReal(52, data.angle); dw.dxfReal(41, data.scale); dw.dxfInt(77, 0); // not double //dw.dxfInt(78, 0); dw.dxfInt(78, 1); dw.dxfReal(53, 45.0); dw.dxfReal(43, 0.0); dw.dxfReal(44, 0.0); dw.dxfReal(45, -0.0883883476483184); dw.dxfReal(46, 0.0883883476483185); dw.dxfInt(79, 0); } dw.dxfInt(98, 0); if (version==DL_VERSION_2000) { dw.dxfString(1001, "ACAD"); dw.dxfReal(1010, data.originX); dw.dxfReal(1020, data.originY); dw.dxfInt(1030, 0.0); } } /** * Writes the beginning of a hatch loop to the file. This * must happen after writing the beginning of a hatch entity. * * @param dw DXF writer * @param data Entity data. * @param attrib Attributes */ void DL_Dxf::writeHatchLoop1(DL_WriterA& dw, const DL_HatchLoopData& data) { dw.dxfInt(92, 1); dw.dxfInt(93, data.numEdges); //dw.dxfInt(97, 0); } /** * Writes the end of a hatch loop to the file. * * @param dw DXF writer * @param data Entity data. * @param attrib Attributes */ void DL_Dxf::writeHatchLoop2(DL_WriterA& dw, const DL_HatchLoopData& /*data*/) { dw.dxfInt(97, 0); } /** * Writes the beginning of a hatch entity to the file. * * @param dw DXF writer * @param data Entity data. * @param attrib Attributes */ void DL_Dxf::writeHatchEdge(DL_WriterA& dw, const DL_HatchEdgeData& data) { if (data.type<1 || data.type>4) { printf("WARNING: unsupported hatch edge type: %d", data.type); } dw.dxfInt(72, data.type); switch (data.type) { // line: case 1: dw.dxfReal(10, data.x1); dw.dxfReal(20, data.y1); dw.dxfReal(11, data.x2); dw.dxfReal(21, data.y2); break; // arc: case 2: dw.dxfReal(10, data.cx); dw.dxfReal(20, data.cy); dw.dxfReal(40, data.radius); dw.dxfReal(50, data.angle1/(2*M_PI)*360.0); dw.dxfReal(51, data.angle2/(2*M_PI)*360.0); dw.dxfInt(73, static_cast((data.ccw))); break; // ellipse arc: case 3: dw.dxfReal(10, data.cx); dw.dxfReal(20, data.cy); dw.dxfReal(11, data.mx); dw.dxfReal(21, data.my); dw.dxfReal(40, data.ratio); dw.dxfReal(50, data.angle1/(2*M_PI)*360.0); dw.dxfReal(51, data.angle2/(2*M_PI)*360.0); dw.dxfInt(73, static_cast((data.ccw))); break; // spline: case 4: dw.dxfInt(94, data.degree); dw.dxfBool(73, data.rational); dw.dxfBool(74, data.periodic); dw.dxfInt(95, data.nKnots); dw.dxfInt(96, data.nControl); for (unsigned int i=0; i0) { dw.dxfInt(97, data.nFit); for (unsigned int i=0; i1.0e-4 || fabs(data.startTangentY)>1.0e-4) { dw.dxfReal(12, data.startTangentX); dw.dxfReal(22, data.startTangentY); } if (fabs(data.endTangentX)>1.0e-4 || fabs(data.endTangentY)>1.0e-4) { dw.dxfReal(13, data.endTangentX); dw.dxfReal(23, data.endTangentY); } break; default: break; } } /** * Writes an image entity. * * @return IMAGEDEF handle. Needed for the IMAGEDEF counterpart. */ int DL_Dxf::writeImage(DL_WriterA& dw, const DL_ImageData& data, const DL_Attributes& attrib) { /*if (data.file.empty()) { std::cerr << "DL_Dxf::writeImage: " << "Image file must not be empty\n"; return; }*/ dw.entity("IMAGE"); dw.entityAttributes(attrib); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbEntity"); dw.dxfString(100, "AcDbRasterImage"); dw.dxfInt(90, 0); } // insertion point dw.dxfReal(10, data.ipx); dw.dxfReal(20, data.ipy); dw.dxfReal(30, data.ipz); // vector along bottom side (1 pixel long) dw.dxfReal(11, data.ux); dw.dxfReal(21, data.uy); dw.dxfReal(31, data.uz); // vector along left side (1 pixel long) dw.dxfReal(12, data.vx); dw.dxfReal(22, data.vy); dw.dxfReal(32, data.vz); // image size in pixel dw.dxfReal(13, data.width); dw.dxfReal(23, data.height); // handle of IMAGEDEF object int handle = static_cast(dw.incHandle()); dw.dxfHex(340, handle); // flags dw.dxfInt(70, 15); // clipping: dw.dxfInt(280, 0); // brightness, contrast, fade dw.dxfInt(281, data.brightness); dw.dxfInt(282, data.contrast); dw.dxfInt(283, data.fade); return handle; } /** * Writes an image definiition entity. */ void DL_Dxf::writeImageDef(DL_WriterA& dw, int handle, const DL_ImageData& data) { /*if (data.file.empty()) { std::cerr << "DL_Dxf::writeImage: " << "Image file must not be empty\n"; return; }*/ dw.dxfString(0, "IMAGEDEF"); if (version==DL_VERSION_2000) { dw.dxfHex(5, handle); } if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbRasterImageDef"); dw.dxfInt(90, 0); } // file name: dw.dxfString(1, data.ref); // image size in pixel dw.dxfReal(10, data.width); dw.dxfReal(20, data.height); dw.dxfReal(11, 1.0); dw.dxfReal(21, 1.0); // loaded: dw.dxfInt(280, 1); // units: dw.dxfInt(281, 0); } /** * Writes a layer to the file. Layers are stored in the * tables section of a DXF file. * * @param dw DXF writer * @param data Entity data from the file * @param attrib Attributes */ void DL_Dxf::writeLayer(DL_WriterA& dw, const DL_LayerData& data, const DL_Attributes& attrib) { if (data.name.empty()) { std::cerr << "DL_Dxf::writeLayer: " << "Layer name must not be empty\n"; return; } int color = attrib.getColor(); if (color>=256) { std::cerr << "Layer color cannot be " << color << ". Changed to 7.\n"; color = 7; } if (data.name == "0") { dw.tableLayerEntry(0x10); } else { dw.tableLayerEntry(); } dw.dxfString(2, data.name); dw.dxfInt(70, data.flags); dw.dxfInt(62, color); if (version>=DL_VERSION_2000 && attrib.getColor24()!=-1) { dw.dxfInt(420, attrib.getColor24()); } dw.dxfString(6, (attrib.getLinetype().length()==0 ? std::string("CONTINUOUS") : attrib.getLinetype())); if (version>=DL_VERSION_2000) { // layer defpoints cannot be plotted std::string lstr = data.name; std::transform(lstr.begin(), lstr.end(), lstr.begin(), tolower); if (lstr=="defpoints") { dw.dxfInt(290, 0); } } if (version>=DL_VERSION_2000 && attrib.getWidth()!=-1) { dw.dxfInt(370, attrib.getWidth()); } if (version>=DL_VERSION_2000) { dw.dxfHex(390, 0xF); } } /** * Writes a line type to the file. Line types are stored in the * tables section of a DXF file. */ void DL_Dxf::writeLinetype(DL_WriterA& dw, const DL_LinetypeData& data) { std::string nameUpper = data.name; std::transform(nameUpper.begin(), nameUpper.end(), nameUpper.begin(), ::toupper); if (data.name.empty()) { std::cerr << "DL_Dxf::writeLinetype: " << "Line type name must not be empty\n"; return; } // ignore BYLAYER, BYBLOCK for R12 if (version=DL_VERSION_R13) { dw.dxfInt(74, 0); } } } } /** * Writes the APPID section to the DXF file. * * @param name Application name */ void DL_Dxf::writeAppid(DL_WriterA& dw, const std::string& name) { if (name.empty()) { std::cerr << "DL_Dxf::writeAppid: " << "Application name must not be empty\n"; return; } std::string n = name; std::transform(n.begin(), n.end(), n.begin(), ::toupper); if (n=="ACAD") { dw.tableAppidEntry(0x12); } else { dw.tableAppidEntry(); } dw.dxfString(2, name); dw.dxfInt(70, 0); } /** * Writes a block's definition (no entities) to the DXF file. */ void DL_Dxf::writeBlock(DL_WriterA& dw, const DL_BlockData& data) { if (data.name.empty()) { std::cerr << "DL_Dxf::writeBlock: " << "Block name must not be empty\n"; return; } std::string n = data.name; std::transform(n.begin(), n.end(), n.begin(), ::toupper); if (n=="*PAPER_SPACE") { dw.sectionBlockEntry(0x1C); } else if (n=="*MODEL_SPACE") { dw.sectionBlockEntry(0x20); } else if (n=="*PAPER_SPACE0") { dw.sectionBlockEntry(0x24); } else { dw.sectionBlockEntry(); } dw.dxfString(2, data.name); dw.dxfInt(70, 0); dw.coord(10, data.bpx, data.bpy, data.bpz); dw.dxfString(3, data.name); dw.dxfString(1, ""); } /** * Writes a block end. * * @param name Block name */ void DL_Dxf::writeEndBlock(DL_WriterA& dw, const std::string& name) { std::string n = name; std::transform(n.begin(), n.end(), n.begin(), ::toupper); if (n=="*PAPER_SPACE") { dw.sectionBlockEntryEnd(0x1D); } else if (n=="*MODEL_SPACE") { dw.sectionBlockEntryEnd(0x21); } else if (n=="*PAPER_SPACE0") { dw.sectionBlockEntryEnd(0x25); } else { dw.sectionBlockEntryEnd(); } } /** * Writes a viewport section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked VPORT section * to make the file readable by Aut*cad. */ void DL_Dxf::writeVPort(DL_WriterA& dw) { dw.dxfString(0, "TABLE"); dw.dxfString(2, "VPORT"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 0x8); } //dw.dxfHex(330, 0); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTable"); } dw.dxfInt(70, 1); dw.dxfString(0, "VPORT"); //dw.dxfHex(5, 0x2F); if (version==DL_VERSION_2000) { dw.handle(); } //dw.dxfHex(330, 8); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbViewportTableRecord"); } dw.dxfString( 2, "*Active"); dw.dxfInt( 70, 0); dw.dxfReal( 10, 0.0); dw.dxfReal( 20, 0.0); dw.dxfReal( 11, 1.0); dw.dxfReal( 21, 1.0); dw.dxfReal( 12, 286.3055555555555); dw.dxfReal( 22, 148.5); dw.dxfReal( 13, 0.0); dw.dxfReal( 23, 0.0); dw.dxfReal( 14, 10.0); dw.dxfReal( 24, 10.0); dw.dxfReal( 15, 10.0); dw.dxfReal( 25, 10.0); dw.dxfReal( 16, 0.0); dw.dxfReal( 26, 0.0); dw.dxfReal( 36, 1.0); dw.dxfReal( 17, 0.0); dw.dxfReal( 27, 0.0); dw.dxfReal( 37, 0.0); dw.dxfReal( 40, 297.0); dw.dxfReal( 41, 1.92798353909465); dw.dxfReal( 42, 50.0); dw.dxfReal( 43, 0.0); dw.dxfReal( 44, 0.0); dw.dxfReal( 50, 0.0); dw.dxfReal( 51, 0.0); dw.dxfInt( 71, 0); dw.dxfInt( 72, 100); dw.dxfInt( 73, 1); dw.dxfInt( 74, 3); dw.dxfInt( 75, 1); dw.dxfInt( 76, 1); dw.dxfInt( 77, 0); dw.dxfInt( 78, 0); if (version==DL_VERSION_2000) { dw.dxfInt(281, 0); dw.dxfInt( 65, 1); dw.dxfReal(110, 0.0); dw.dxfReal(120, 0.0); dw.dxfReal(130, 0.0); dw.dxfReal(111, 1.0); dw.dxfReal(121, 0.0); dw.dxfReal(131, 0.0); dw.dxfReal(112, 0.0); dw.dxfReal(122, 1.0); dw.dxfReal(132, 0.0); dw.dxfInt( 79, 0); dw.dxfReal(146, 0.0); } dw.dxfString( 0, "ENDTAB"); } /** * Writes a style section. This section is needed in DL_VERSION_R13. */ void DL_Dxf::writeStyle(DL_WriterA& dw, const DL_StyleData& style) { // dw.dxfString( 0, "TABLE"); // dw.dxfString( 2, "STYLE"); // if (version==DL_VERSION_2000) { // dw.dxfHex(5, 3); // } //dw.dxfHex(330, 0); // if (version==DL_VERSION_2000) { // dw.dxfString(100, "AcDbSymbolTable"); // } // dw.dxfInt( 70, 1); dw.dxfString( 0, "STYLE"); if (version==DL_VERSION_2000) { if (style.name=="Standard") { //dw.dxfHex(5, 0x11); styleHandleStd = dw.handle(); } else { dw.handle(); } } //dw.dxfHex(330, 3); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbTextStyleTableRecord"); } dw.dxfString( 2, style.name); dw.dxfInt( 70, style.flags); dw.dxfReal( 40, style.fixedTextHeight); dw.dxfReal( 41, style.widthFactor); dw.dxfReal( 50, style.obliqueAngle); dw.dxfInt( 71, style.textGenerationFlags); dw.dxfReal( 42, style.lastHeightUsed); if (version==DL_VERSION_2000) { dw.dxfString( 3, ""); dw.dxfString( 4, ""); dw.dxfString(1001, "ACAD"); //dw.dxfString(1000, style.name); dw.dxfString(1000, style.primaryFontFile); int xFlags = 0; if (style.bold) { xFlags = xFlags|0x2000000; } if (style.italic) { xFlags = xFlags|0x1000000; } dw.dxfInt(1071, xFlags); } else { dw.dxfString( 3, style.primaryFontFile); dw.dxfString( 4, style.bigFontFile); } //dw.dxfString( 0, "ENDTAB"); } /** * Writes a view section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked VIEW section * to make the file readable by Aut*cad. */ void DL_Dxf::writeView(DL_WriterA& dw) { dw.dxfString( 0, "TABLE"); dw.dxfString( 2, "VIEW"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 6); } //dw.dxfHex(330, 0); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTable"); } dw.dxfInt( 70, 0); dw.dxfString( 0, "ENDTAB"); } /** * Writes a ucs section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked UCS section * to make the file readable by Aut*cad. */ void DL_Dxf::writeUcs(DL_WriterA& dw) { dw.dxfString( 0, "TABLE"); dw.dxfString( 2, "UCS"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 7); } //dw.dxfHex(330, 0); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTable"); } dw.dxfInt( 70, 0); dw.dxfString( 0, "ENDTAB"); } /** * Writes a dimstyle section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked DIMSTYLE section * to make the file readable by Aut*cad. */ void DL_Dxf::writeDimStyle(DL_WriterA& dw, double dimasz, double dimexe, double dimexo, double dimgap, double dimtxt) { dw.dxfString( 0, "TABLE"); dw.dxfString( 2, "DIMSTYLE"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 0xA); dw.dxfString(100, "AcDbSymbolTable"); } dw.dxfInt( 70, 1); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbDimStyleTable"); dw.dxfInt( 71, 0); } dw.dxfString( 0, "DIMSTYLE"); if (version==DL_VERSION_2000) { dw.dxfHex(105, 0x27); } //dw.handle(105); //dw.dxfHex(330, 0xA); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbDimStyleTableRecord"); } dw.dxfString( 2, "Standard"); if (version==DL_VERSION_R12) { dw.dxfString( 3, ""); dw.dxfString( 4, ""); dw.dxfString( 5, ""); dw.dxfString( 6, ""); dw.dxfString( 7, ""); dw.dxfReal( 40, 1.0); } dw.dxfReal( 41, dimasz); dw.dxfReal( 42, dimexo); dw.dxfReal( 43, 3.75); dw.dxfReal( 44, dimexe); if (version==DL_VERSION_R12) { dw.dxfReal( 45, 0.0); dw.dxfReal( 46, 0.0); dw.dxfReal( 47, 0.0); dw.dxfReal( 48, 0.0); } dw.dxfInt( 70, 0); if (version==DL_VERSION_R12) { dw.dxfInt( 71, 0); dw.dxfInt( 72, 0); } dw.dxfInt( 73, 0); dw.dxfInt( 74, 0); if (version==DL_VERSION_R12) { dw.dxfInt( 75, 0); dw.dxfInt( 76, 0); } dw.dxfInt( 77, 1); dw.dxfInt( 78, 8); dw.dxfReal(140, dimtxt); dw.dxfReal(141, 2.5); if (version==DL_VERSION_R12) { dw.dxfReal(142, 0.0); } dw.dxfReal(143, 0.03937007874016); if (version==DL_VERSION_R12) { dw.dxfReal(144, 1.0); dw.dxfReal(145, 0.0); dw.dxfReal(146, 1.0); } dw.dxfReal(147, dimgap); if (version==DL_VERSION_R12) { dw.dxfInt(170, 0); } dw.dxfInt(171, 3); dw.dxfInt(172, 1); if (version==DL_VERSION_R12) { dw.dxfInt(173, 0); dw.dxfInt(174, 0); dw.dxfInt(175, 0); dw.dxfInt(176, 0); dw.dxfInt(177, 0); dw.dxfInt(178, 0); } if (version==DL_VERSION_2000) { dw.dxfInt(271, 2); dw.dxfInt(272, 2); dw.dxfInt(274, 3); dw.dxfInt(278, 44); dw.dxfInt(283, 0); dw.dxfInt(284, 8); dw.dxfHex(340, static_cast(styleHandleStd)); //dw.dxfHex(340, 0x11); } // * / dw.dxfString( 0, "ENDTAB"); } /** * Writes a blockrecord section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked BLOCKRECORD section * to make the file readable by Aut*cad. */ void DL_Dxf::writeBlockRecord(DL_WriterA& dw) { dw.dxfString( 0, "TABLE"); dw.dxfString( 2, "BLOCK_RECORD"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 1); } //dw.dxfHex(330, 0); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTable"); } dw.dxfInt( 70, 1); dw.dxfString( 0, "BLOCK_RECORD"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 0x1F); } //int msh = dw.handle(); //dw.setModelSpaceHandle(msh); //dw.dxfHex(330, 1); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbBlockTableRecord"); } dw.dxfString( 2, "*Model_Space"); dw.dxfHex(340, 0x22); dw.dxfString( 0, "BLOCK_RECORD"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 0x1B); } //int psh = dw.handle(); //dw.setPaperSpaceHandle(psh); //dw.dxfHex(330, 1); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbBlockTableRecord"); } dw.dxfString( 2, "*Paper_Space"); dw.dxfHex(340, 0x1E); dw.dxfString( 0, "BLOCK_RECORD"); if (version==DL_VERSION_2000) { dw.dxfHex(5, 0x23); } //int ps0h = dw.handle(); //dw.setPaperSpace0Handle(ps0h); //dw.dxfHex(330, 1); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbBlockTableRecord"); } dw.dxfString( 2, "*Paper_Space0"); dw.dxfHex(340, 0x26); //dw.dxfString( 0, "ENDTAB"); } /** * Writes a single block record with the given name. */ void DL_Dxf::writeBlockRecord(DL_WriterA& dw, const std::string& name) { dw.dxfString( 0, "BLOCK_RECORD"); if (version==DL_VERSION_2000) { dw.handle(); } //dw->dxfHex(330, 1); if (version==DL_VERSION_2000) { dw.dxfString(100, "AcDbSymbolTableRecord"); dw.dxfString(100, "AcDbBlockTableRecord"); } dw.dxfString( 2, name); dw.dxfHex(340, 0); } /** * Writes a objects section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked OBJECTS section * to make the file readable by Aut*cad. */ void DL_Dxf::writeObjects(DL_WriterA& dw, const std::string& appDictionaryName) { dw.dxfString( 0, "SECTION"); dw.dxfString( 2, "OBJECTS"); dw.dxfString( 0, "DICTIONARY"); dw.dxfHex(5, 0xC); dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(280, 0); dw.dxfInt(281, 1); dw.dxfString( 3, "ACAD_GROUP"); dw.dxfHex(350, 0xD); dw.dxfString( 3, "ACAD_LAYOUT"); dw.dxfHex(350, 0x1A); dw.dxfString( 3, "ACAD_MLINESTYLE"); dw.dxfHex(350, 0x17); dw.dxfString( 3, "ACAD_PLOTSETTINGS"); dw.dxfHex(350, 0x19); dw.dxfString( 3, "ACAD_PLOTSTYLENAME"); dw.dxfHex(350, 0xE); dw.dxfString( 3, "AcDbVariableDictionary"); int acDbVariableDictionaryHandle = static_cast(dw.handle(350)); //int acDbVariableDictionaryHandle = dw.getNextHandle(); //dw.dxfHex(350, acDbVariableDictionaryHandle); //dw.incHandle(); if (appDictionaryName.length()!=0) { dw.dxfString( 3, appDictionaryName); appDictionaryHandle = dw.handle(350); //appDictionaryHandle = dw.getNextHandle(); //dw.dxfHex(350, appDictionaryHandle); //dw.incHandle(); } dw.dxfString( 0, "DICTIONARY"); dw.dxfHex(5, 0xD); //dw.handle(); // D //dw.dxfHex(330, 0xC); dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(280, 0); dw.dxfInt(281, 1); dw.dxfString( 0, "ACDBDICTIONARYWDFLT"); dw.dxfHex(5, 0xE); //dicId4 = dw.handle(); // E //dw.dxfHex(330, 0xC); // C dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(281, 1); dw.dxfString( 3, "Normal"); dw.dxfHex(350, 0xF); //dw.dxfHex(350, dw.getNextHandle()+5); // F dw.dxfString(100, "AcDbDictionaryWithDefault"); dw.dxfHex(340, 0xF); //dw.dxfHex(340, dw.getNextHandle()+5); // F dw.dxfString( 0, "ACDBPLACEHOLDER"); dw.dxfHex(5, 0xF); //dw.handle(); // F //dw.dxfHex(330, dicId4); // E dw.dxfString( 0, "DICTIONARY"); //dicId3 = dw.handle(); // 17 dw.dxfHex(5, 0x17); //dw.dxfHex(330, 0xC); // C dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(280, 0); dw.dxfInt(281, 1); dw.dxfString( 3, "Standard"); dw.dxfHex(350, 0x18); //dw.dxfHex(350, dw.getNextHandle()+5); // 18 dw.dxfString( 0, "MLINESTYLE"); dw.dxfHex(5, 0x18); //dw.handle(); // 18 //dw.dxfHex(330, dicId3); // 17 dw.dxfString(100, "AcDbMlineStyle"); dw.dxfString( 2, "STANDARD"); dw.dxfInt( 70, 0); dw.dxfString( 3, ""); dw.dxfInt( 62, 256); dw.dxfReal( 51, 90.0); dw.dxfReal( 52, 90.0); dw.dxfInt( 71, 2); dw.dxfReal( 49, 0.5); dw.dxfInt( 62, 256); dw.dxfString( 6, "BYLAYER"); dw.dxfReal( 49, -0.5); dw.dxfInt( 62, 256); dw.dxfString( 6, "BYLAYER"); dw.dxfString( 0, "DICTIONARY"); dw.dxfHex(5, 0x19); //dw.handle(); // 17 //dw.dxfHex(330, 0xC); // C dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(280, 0); dw.dxfInt(281, 1); dw.dxfString( 0, "DICTIONARY"); //dicId2 = dw.handle(); // 1A dw.dxfHex(5, 0x1A); //dw.dxfHex(330, 0xC); dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(281, 1); dw.dxfString( 3, "Layout1"); dw.dxfHex(350, 0x1E); //dw.dxfHex(350, dw.getNextHandle()+2); // 1E dw.dxfString( 3, "Layout2"); dw.dxfHex(350, 0x26); //dw.dxfHex(350, dw.getNextHandle()+4); // 26 dw.dxfString( 3, "Model"); dw.dxfHex(350, 0x22); //dw.dxfHex(350, dw.getNextHandle()+5); // 22 dw.dxfString( 0, "LAYOUT"); dw.dxfHex(5, 0x1E); //dw.handle(); // 1E //dw.dxfHex(330, dicId2); // 1A dw.dxfString(100, "AcDbPlotSettings"); dw.dxfString( 1, ""); dw.dxfString( 2, "none_device"); dw.dxfString( 4, ""); dw.dxfString( 6, ""); dw.dxfReal( 40, 0.0); dw.dxfReal( 41, 0.0); dw.dxfReal( 42, 0.0); dw.dxfReal( 43, 0.0); dw.dxfReal( 44, 0.0); dw.dxfReal( 45, 0.0); dw.dxfReal( 46, 0.0); dw.dxfReal( 47, 0.0); dw.dxfReal( 48, 0.0); dw.dxfReal( 49, 0.0); dw.dxfReal(140, 0.0); dw.dxfReal(141, 0.0); dw.dxfReal(142, 1.0); dw.dxfReal(143, 1.0); dw.dxfInt( 70, 688); dw.dxfInt( 72, 0); dw.dxfInt( 73, 0); dw.dxfInt( 74, 5); dw.dxfString( 7, ""); dw.dxfInt( 75, 16); dw.dxfReal(147, 1.0); dw.dxfReal(148, 0.0); dw.dxfReal(149, 0.0); dw.dxfString(100, "AcDbLayout"); dw.dxfString( 1, "Layout1"); dw.dxfInt( 70, 1); dw.dxfInt( 71, 1); dw.dxfReal( 10, 0.0); dw.dxfReal( 20, 0.0); dw.dxfReal( 11, 420.0); dw.dxfReal( 21, 297.0); dw.dxfReal( 12, 0.0); dw.dxfReal( 22, 0.0); dw.dxfReal( 32, 0.0); dw.dxfReal( 14, 1.000000000000000E+20); dw.dxfReal( 24, 1.000000000000000E+20); dw.dxfReal( 34, 1.000000000000000E+20); dw.dxfReal( 15, -1.000000000000000E+20); dw.dxfReal( 25, -1.000000000000000E+20); dw.dxfReal( 35, -1.000000000000000E+20); dw.dxfReal(146, 0.0); dw.dxfReal( 13, 0.0); dw.dxfReal( 23, 0.0); dw.dxfReal( 33, 0.0); dw.dxfReal( 16, 1.0); dw.dxfReal( 26, 0.0); dw.dxfReal( 36, 0.0); dw.dxfReal( 17, 0.0); dw.dxfReal( 27, 1.0); dw.dxfReal( 37, 0.0); dw.dxfInt( 76, 0); //dw.dxfHex(330, dw.getPaperSpaceHandle()); // 1B dw.dxfHex(330, 0x1B); dw.dxfString( 0, "LAYOUT"); dw.dxfHex(5, 0x22); //dw.handle(); // 22 //dw.dxfHex(330, dicId2); // 1A dw.dxfString(100, "AcDbPlotSettings"); dw.dxfString( 1, ""); dw.dxfString( 2, "none_device"); dw.dxfString( 4, ""); dw.dxfString( 6, ""); dw.dxfReal( 40, 0.0); dw.dxfReal( 41, 0.0); dw.dxfReal( 42, 0.0); dw.dxfReal( 43, 0.0); dw.dxfReal( 44, 0.0); dw.dxfReal( 45, 0.0); dw.dxfReal( 46, 0.0); dw.dxfReal( 47, 0.0); dw.dxfReal( 48, 0.0); dw.dxfReal( 49, 0.0); dw.dxfReal(140, 0.0); dw.dxfReal(141, 0.0); dw.dxfReal(142, 1.0); dw.dxfReal(143, 1.0); dw.dxfInt( 70, 1712); dw.dxfInt( 72, 0); dw.dxfInt( 73, 0); dw.dxfInt( 74, 0); dw.dxfString( 7, ""); dw.dxfInt( 75, 0); dw.dxfReal(147, 1.0); dw.dxfReal(148, 0.0); dw.dxfReal(149, 0.0); dw.dxfString(100, "AcDbLayout"); dw.dxfString( 1, "Model"); dw.dxfInt( 70, 1); dw.dxfInt( 71, 0); dw.dxfReal( 10, 0.0); dw.dxfReal( 20, 0.0); dw.dxfReal( 11, 12.0); dw.dxfReal( 21, 9.0); dw.dxfReal( 12, 0.0); dw.dxfReal( 22, 0.0); dw.dxfReal( 32, 0.0); dw.dxfReal( 14, 0.0); dw.dxfReal( 24, 0.0); dw.dxfReal( 34, 0.0); dw.dxfReal( 15, 0.0); dw.dxfReal( 25, 0.0); dw.dxfReal( 35, 0.0); dw.dxfReal(146, 0.0); dw.dxfReal( 13, 0.0); dw.dxfReal( 23, 0.0); dw.dxfReal( 33, 0.0); dw.dxfReal( 16, 1.0); dw.dxfReal( 26, 0.0); dw.dxfReal( 36, 0.0); dw.dxfReal( 17, 0.0); dw.dxfReal( 27, 1.0); dw.dxfReal( 37, 0.0); dw.dxfInt( 76, 0); //dw.dxfHex(330, dw.getModelSpaceHandle()); // 1F dw.dxfHex(330, 0x1F); dw.dxfString( 0, "LAYOUT"); //dw.handle(); // 26 dw.dxfHex(5, 0x26); //dw.dxfHex(330, dicId2); // 1A dw.dxfString(100, "AcDbPlotSettings"); dw.dxfString( 1, ""); dw.dxfString( 2, "none_device"); dw.dxfString( 4, ""); dw.dxfString( 6, ""); dw.dxfReal( 40, 0.0); dw.dxfReal( 41, 0.0); dw.dxfReal( 42, 0.0); dw.dxfReal( 43, 0.0); dw.dxfReal( 44, 0.0); dw.dxfReal( 45, 0.0); dw.dxfReal( 46, 0.0); dw.dxfReal( 47, 0.0); dw.dxfReal( 48, 0.0); dw.dxfReal( 49, 0.0); dw.dxfReal(140, 0.0); dw.dxfReal(141, 0.0); dw.dxfReal(142, 1.0); dw.dxfReal(143, 1.0); dw.dxfInt( 70, 688); dw.dxfInt( 72, 0); dw.dxfInt( 73, 0); dw.dxfInt( 74, 5); dw.dxfString( 7, ""); dw.dxfInt( 75, 16); dw.dxfReal(147, 1.0); dw.dxfReal(148, 0.0); dw.dxfReal(149, 0.0); dw.dxfString(100, "AcDbLayout"); dw.dxfString( 1, "Layout2"); dw.dxfInt( 70, 1); dw.dxfInt( 71, 2); dw.dxfReal( 10, 0.0); dw.dxfReal( 20, 0.0); dw.dxfReal( 11, 12.0); dw.dxfReal( 21, 9.0); dw.dxfReal( 12, 0.0); dw.dxfReal( 22, 0.0); dw.dxfReal( 32, 0.0); dw.dxfReal( 14, 0.0); dw.dxfReal( 24, 0.0); dw.dxfReal( 34, 0.0); dw.dxfReal( 15, 0.0); dw.dxfReal( 25, 0.0); dw.dxfReal( 35, 0.0); dw.dxfReal(146, 0.0); dw.dxfReal( 13, 0.0); dw.dxfReal( 23, 0.0); dw.dxfReal( 33, 0.0); dw.dxfReal( 16, 1.0); dw.dxfReal( 26, 0.0); dw.dxfReal( 36, 0.0); dw.dxfReal( 17, 0.0); dw.dxfReal( 27, 1.0); dw.dxfReal( 37, 0.0); dw.dxfInt( 76, 0); //dw.dxfHex(330, dw.getPaperSpace0Handle()); // 23 dw.dxfHex(330, 0x23); dw.dxfString( 0, "DICTIONARY"); //dw.dxfHex(5, 0x2C); //dicId5 = dw.dxfHex(5, acDbVariableDictionaryHandle); //dw.handle(); // 2C //dw.dxfHex(330, 0xC); // C dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(281, 1); dw.dxfString( 3, "DIMASSOC"); //dw.dxfHex(350, 0x2F); dw.dxfHex(350, static_cast(dw.getNextHandle()+1)); // 2E dw.dxfString( 3, "HIDETEXT"); //dw.dxfHex(350, 0x2E); dw.dxfHex(350, static_cast(dw.getNextHandle())); // 2D dw.dxfString( 0, "DICTIONARYVAR"); //dw.dxfHex(5, 0x2E); dw.handle(); // 2E //dw.dxfHex(330, dicId5); // 2C dw.dxfString(100, "DictionaryVariables"); dw.dxfInt(280, 0); dw.dxfInt( 1, 2); dw.dxfString( 0, "DICTIONARYVAR"); //dw.dxfHex(5, 0x2D); dw.handle(); // 2D //dw.dxfHex(330, dicId5); // 2C dw.dxfString(100, "DictionaryVariables"); dw.dxfInt(280, 0); dw.dxfInt( 1, 1); } void DL_Dxf::writeAppDictionary(DL_WriterA& dw) { dw.dxfString( 0, "DICTIONARY"); //dw.handle(); dw.dxfHex(5, static_cast(appDictionaryHandle)); dw.dxfString(100, "AcDbDictionary"); dw.dxfInt(281, 1); } int DL_Dxf::writeDictionaryEntry(DL_WriterA& dw, const std::string& name) { dw.dxfString( 3, name); int handle = static_cast(dw.getNextHandle()); dw.dxfHex(350, handle); dw.incHandle(); return handle; } void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, int value) { dw.dxfString( 0, "XRECORD"); dw.dxfHex(5, handle); dw.dxfHex(330, static_cast(appDictionaryHandle)); dw.dxfString(100, "AcDbXrecord"); dw.dxfInt(280, 1); dw.dxfInt(90, value); } void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, double value) { dw.dxfString( 0, "XRECORD"); dw.dxfHex(5, handle); dw.dxfHex(330, static_cast(appDictionaryHandle)); dw.dxfString(100, "AcDbXrecord"); dw.dxfInt(280, 1); dw.dxfReal(40, value); } void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, bool value) { dw.dxfString( 0, "XRECORD"); dw.dxfHex(5, handle); dw.dxfHex(330, static_cast(appDictionaryHandle)); dw.dxfString(100, "AcDbXrecord"); dw.dxfInt(280, 1); dw.dxfBool(290, value); } void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, const std::string& value) { dw.dxfString( 0, "XRECORD"); dw.dxfHex(5, handle); dw.dxfHex(330, static_cast(appDictionaryHandle)); dw.dxfString(100, "AcDbXrecord"); dw.dxfInt(280, 1); dw.dxfString(1000, value); } /** * Writes the end of the objects section. This section is needed in DL_VERSION_R13. * Note that this method currently only writes a faked OBJECTS section * to make the file readable by Aut*cad. */ void DL_Dxf::writeObjectsEnd(DL_WriterA& dw) { dw.dxfString( 0, "ENDSEC"); } /** * Writes a comment to the DXF file. */ void DL_Dxf::writeComment(DL_WriterA& dw, const std::string& comment) { dw.dxfString(999, comment); } /** * Checks if the given variable is known by the given DXF version. */ bool DL_Dxf::checkVariable(const char* var, DL_Codes::version version) { if (version>=DL_VERSION_2000) { return true; } else if (version==DL_VERSION_R12) { // these are all the variables recognized by dxf r12: if (!strcmp(var, "$ACADVER")) { return true; } if (!strcmp(var, "$ACADVER")) { return true; } if (!strcmp(var, "$ANGBASE")) { return true; } if (!strcmp(var, "$ANGDIR")) { return true; } if (!strcmp(var, "$ATTDIA")) { return true; } if (!strcmp(var, "$ATTMODE")) { return true; } if (!strcmp(var, "$ATTREQ")) { return true; } if (!strcmp(var, "$AUNITS")) { return true; } if (!strcmp(var, "$AUPREC")) { return true; } if (!strcmp(var, "$AXISMODE")) { return true; } if (!strcmp(var, "$AXISUNIT")) { return true; } if (!strcmp(var, "$BLIPMODE")) { return true; } if (!strcmp(var, "$CECOLOR")) { return true; } if (!strcmp(var, "$CELTYPE")) { return true; } if (!strcmp(var, "$CHAMFERA")) { return true; } if (!strcmp(var, "$CHAMFERB")) { return true; } if (!strcmp(var, "$CLAYER")) { return true; } if (!strcmp(var, "$COORDS")) { return true; } if (!strcmp(var, "$DIMALT")) { return true; } if (!strcmp(var, "$DIMALTD")) { return true; } if (!strcmp(var, "$DIMALTF")) { return true; } if (!strcmp(var, "$DIMAPOST")) { return true; } if (!strcmp(var, "$DIMASO")) { return true; } if (!strcmp(var, "$DIMASZ")) { return true; } if (!strcmp(var, "$DIMBLK")) { return true; } if (!strcmp(var, "$DIMBLK1")) { return true; } if (!strcmp(var, "$DIMBLK2")) { return true; } if (!strcmp(var, "$DIMCEN")) { return true; } if (!strcmp(var, "$DIMCLRD")) { return true; } if (!strcmp(var, "$DIMCLRE")) { return true; } if (!strcmp(var, "$DIMCLRT")) { return true; } if (!strcmp(var, "$DIMDLE")) { return true; } if (!strcmp(var, "$DIMDLI")) { return true; } if (!strcmp(var, "$DIMEXE")) { return true; } if (!strcmp(var, "$DIMEXO")) { return true; } if (!strcmp(var, "$DIMGAP")) { return true; } if (!strcmp(var, "$DIMLFAC")) { return true; } if (!strcmp(var, "$DIMLIM")) { return true; } if (!strcmp(var, "$DIMPOST")) { return true; } if (!strcmp(var, "$DIMRND")) { return true; } if (!strcmp(var, "$DIMSAH")) { return true; } if (!strcmp(var, "$DIMSCALE")) { return true; } if (!strcmp(var, "$DIMSE1")) { return true; } if (!strcmp(var, "$DIMSE2")) { return true; } if (!strcmp(var, "$DIMSHO")) { return true; } if (!strcmp(var, "$DIMSOXD")) { return true; } if (!strcmp(var, "$DIMSTYLE")) { return true; } if (!strcmp(var, "$DIMTAD")) { return true; } if (!strcmp(var, "$DIMTFAC")) { return true; } if (!strcmp(var, "$DIMTIH")) { return true; } if (!strcmp(var, "$DIMTIX")) { return true; } if (!strcmp(var, "$DIMTM")) { return true; } if (!strcmp(var, "$DIMTOFL")) { return true; } if (!strcmp(var, "$DIMTOH")) { return true; } if (!strcmp(var, "$DIMTOL")) { return true; } if (!strcmp(var, "$DIMTP")) { return true; } if (!strcmp(var, "$DIMTSZ")) { return true; } if (!strcmp(var, "$DIMTVP")) { return true; } if (!strcmp(var, "$DIMTXT")) { return true; } if (!strcmp(var, "$DIMZIN")) { return true; } if (!strcmp(var, "$DWGCODEPAGE")) { return true; } if (!strcmp(var, "$DRAGMODE")) { return true; } if (!strcmp(var, "$ELEVATION")) { return true; } if (!strcmp(var, "$EXTMAX")) { return true; } if (!strcmp(var, "$EXTMIN")) { return true; } if (!strcmp(var, "$FILLETRAD")) { return true; } if (!strcmp(var, "$FILLMODE")) { return true; } if (!strcmp(var, "$HANDLING")) { return true; } if (!strcmp(var, "$HANDSEED")) { return true; } if (!strcmp(var, "$INSBASE")) { return true; } if (!strcmp(var, "$LIMCHECK")) { return true; } if (!strcmp(var, "$LIMMAX")) { return true; } if (!strcmp(var, "$LIMMIN")) { return true; } if (!strcmp(var, "$LTSCALE")) { return true; } if (!strcmp(var, "$LUNITS")) { return true; } if (!strcmp(var, "$LUPREC")) { return true; } if (!strcmp(var, "$MAXACTVP")) { return true; } if (!strcmp(var, "$MENU")) { return true; } if (!strcmp(var, "$MIRRTEXT")) { return true; } if (!strcmp(var, "$ORTHOMODE")) { return true; } if (!strcmp(var, "$OSMODE")) { return true; } if (!strcmp(var, "$PDMODE")) { return true; } if (!strcmp(var, "$PDSIZE")) { return true; } if (!strcmp(var, "$PELEVATION")) { return true; } if (!strcmp(var, "$PEXTMAX")) { return true; } if (!strcmp(var, "$PEXTMIN")) { return true; } if (!strcmp(var, "$PLIMCHECK")) { return true; } if (!strcmp(var, "$PLIMMAX")) { return true; } if (!strcmp(var, "$PLIMMIN")) { return true; } if (!strcmp(var, "$PLINEGEN")) { return true; } if (!strcmp(var, "$PLINEWID")) { return true; } if (!strcmp(var, "$PSLTSCALE")) { return true; } if (!strcmp(var, "$PUCSNAME")) { return true; } if (!strcmp(var, "$PUCSORG")) { return true; } if (!strcmp(var, "$PUCSXDIR")) { return true; } if (!strcmp(var, "$PUCSYDIR")) { return true; } if (!strcmp(var, "$QTEXTMODE")) { return true; } if (!strcmp(var, "$REGENMODE")) { return true; } if (!strcmp(var, "$SHADEDGE")) { return true; } if (!strcmp(var, "$SHADEDIF")) { return true; } if (!strcmp(var, "$SKETCHINC")) { return true; } if (!strcmp(var, "$SKPOLY")) { return true; } if (!strcmp(var, "$SPLFRAME")) { return true; } if (!strcmp(var, "$SPLINESEGS")) { return true; } if (!strcmp(var, "$SPLINETYPE")) { return true; } if (!strcmp(var, "$SURFTAB1")) { return true; } if (!strcmp(var, "$SURFTAB2")) { return true; } if (!strcmp(var, "$SURFTYPE")) { return true; } if (!strcmp(var, "$SURFU")) { return true; } if (!strcmp(var, "$SURFV")) { return true; } if (!strcmp(var, "$TDCREATE")) { return true; } if (!strcmp(var, "$TDINDWG")) { return true; } if (!strcmp(var, "$TDUPDATE")) { return true; } if (!strcmp(var, "$TDUSRTIMER")) { return true; } if (!strcmp(var, "$TEXTSIZE")) { return true; } if (!strcmp(var, "$TEXTSTYLE")) { return true; } if (!strcmp(var, "$THICKNESS")) { return true; } if (!strcmp(var, "$TILEMODE")) { return true; } if (!strcmp(var, "$TRACEWID")) { return true; } if (!strcmp(var, "$UCSNAME")) { return true; } if (!strcmp(var, "$UCSORG")) { return true; } if (!strcmp(var, "$UCSXDIR")) { return true; } if (!strcmp(var, "$UCSYDIR")) { return true; } if (!strcmp(var, "$UNITMODE")) { return true; } if (!strcmp(var, "$USERI1")) { return true; } if (!strcmp(var, "$USERR1")) { return true; } if (!strcmp(var, "$USRTIMER")) { return true; } if (!strcmp(var, "$VISRETAIN")) { return true; } if (!strcmp(var, "$WORLDVIEW")) { return true; } if (!strcmp(var, "$FASTZOOM")) { return true; } if (!strcmp(var, "$GRIDMODE")) { return true; } if (!strcmp(var, "$GRIDUNIT")) { return true; } if (!strcmp(var, "$SNAPANG")) { return true; } if (!strcmp(var, "$SNAPBASE")) { return true; } if (!strcmp(var, "$SNAPISOPAIR")) { return true; } if (!strcmp(var, "$SNAPMODE")) { return true; } if (!strcmp(var, "$SNAPSTYLE")) { return true; } if (!strcmp(var, "$SNAPUNIT")) { return true; } if (!strcmp(var, "$VIEWCTR")) { return true; } if (!strcmp(var, "$VIEWDIR")) { return true; } if (!strcmp(var, "$VIEWSIZE")) { return true; } return false; } return false; } /** * @returns the library version as int (4 bytes, each byte one version number). * e.g. if str = "2.0.2.0" getLibVersion returns 0x02000200 */ int DL_Dxf::getLibVersion(const std::string& str) { int d[4]; int idx = 0; //char v[4][5]; std::string v[4]; int ret = 0; for (unsigned int i=0; i=2) { d[3] = static_cast(str.length()); v[0] = str.substr(0, d[0]); v[1] = str.substr(d[0]+1, d[1]-d[0]-1); v[2] = str.substr(d[1]+1, d[2]-d[1]-1); if (idx>=3) { v[3] = str.substr(d[2]+1, d[3]-d[2]-1); } else { v[3] = "0"; } ret = (atoi(v[0].c_str())<<(3*8)) + (atoi(v[1].c_str())<<(2*8)) + (atoi(v[2].c_str())<<(1*8)) + (atoi(v[3].c_str())<<(0*8)); return ret; } else { std::cerr << "DL_Dxf::getLibVersion: invalid version number: " << str << "\n"; return 0; } } /** * Converts the given string into a double or returns the given * default valud (def) if value is NULL or empty. */ //double DL_Dxf::toReal(const char* value, double def) { // if (value!=NULL && value[0] != '\0') { // printf("toReal: not empty: %s\n", value); // printf("toReal: val: %f\n", atof(value)); // printf("toReal: 0: %d\n", value[0]); // printf("toReal: 1: %d\n", value[1]); // printf("toReal: 2: %d\n", value[2]); // double ret; // if (strchr(value, ',') != NULL) { // char* tmp = new char[strlen(value)+1]; // strcpy(tmp, value); // DL_WriterA::strReplace(tmp, ',', '.'); // ret = atof(tmp); // delete[] tmp; // } // else { // ret = atof(value); // } // return ret; // } else { // return def; // } //} /** * Some test routines. */ void DL_Dxf::test() { char* buf1; char* buf2; char* buf3; char* buf4; char* buf5; char* buf6; buf1 = new char[10]; buf2 = new char[10]; buf3 = new char[10]; buf4 = new char[10]; buf5 = new char[10]; buf6 = new char[10]; strcpy(buf1, " 10\n"); strcpy(buf2, "10"); strcpy(buf3, "10\n"); strcpy(buf4, " 10 \n"); strcpy(buf5, " 10 \r"); strcpy(buf6, "\t10 \n"); std::cout << "1 buf1: '" << buf1 << "'\n"; stripWhiteSpace(&buf1); std::cout << "2 buf1: '" << buf1 << "'\n"; //assert(!strcmp(buf1, "10")); std::cout << "1 buf2: '" << buf2 << "'\n"; stripWhiteSpace(&buf2); std::cout << "2 buf2: '" << buf2 << "'\n"; std::cout << "1 buf3: '" << buf3 << "'\n"; stripWhiteSpace(&buf3); std::cout << "2 buf3: '" << buf3 << "'\n"; std::cout << "1 buf4: '" << buf4 << "'\n"; stripWhiteSpace(&buf4); std::cout << "2 buf4: '" << buf4 << "'\n"; std::cout << "1 buf5: '" << buf5 << "'\n"; stripWhiteSpace(&buf5); std::cout << "2 buf5: '" << buf5 << "'\n"; std::cout << "1 buf6: '" << buf6 << "'\n"; stripWhiteSpace(&buf6); std::cout << "2 buf6: '" << buf6 << "'\n"; }