/**************************************************************************** ** 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; vertices = NULL; maxVertices = 0; vertexIndex = 0; knots = NULL; maxKnots = 0; knotIndex = 0; weights = NULL; weightIndex = 0; controlPoints = NULL; maxControlPoints = 0; controlPointIndex = 0; fitPoints = NULL; maxFitPoints = 0; fitPointIndex = 0; leaderVertices = NULL; maxLeaderVertices = 0; leaderVertexIndex = 0; // Aux members, initialized here to avoid warnings in analysers firstHatchLoop = true; xRecordValues = false; groupCode = 0; currentObjectType = 0; settingValue[0] = 0; firstCall = true; libVersion = 0; appDictionaryHandle = 0; styleHandleStd = 0; } /** * Destructor. */ DL_Dxf::~DL_Dxf() { if( vertices!=NULL ) { delete[] vertices; } if( knots!=NULL ) { delete[] knots; } if( controlPoints!=NULL ) { delete[] controlPoints; } if( fitPoints!=NULL ) { delete[] fitPoints; } if( weights!=NULL ) { delete[] weights; } if( leaderVertices!=NULL ) { 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 the file pointer to read * @param creationInterface * Pointer to the class which takes care of the entities in the file. * * @retval true if fp is valid (i.e. not NULL), false otherwise. */ bool DL_Dxf::in( FILE* fp, DL_CreationInterface* creationInterface ) { firstCall = true; currentObjectType = DL_UNKNOWN; if( fp ) { std::locale oldLocale = std::locale::global( std::locale( "C" ) ); // use dot in numbers while( readDxfGroups( fp, creationInterface ) ) { } std::locale::global( oldLocale ); fclose( fp ); return true; } return false; } /** * @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 * Note: file is not very well utf8 compatible, depending on the platform. * @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 ) { std::locale oldLocale = std::locale::global( std::locale( "C" ) ); // use dot in numbers while( readDxfGroups( fp, creationInterface ) ) { } std::locale::global( oldLocale ); fclose( fp ); return true; } return false; } /** * Reads a DXF file from an existing stream. * * @param stream The input 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::istream& 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, false ) ) { groupCode = (unsigned int) toInt( groupCodeTmp ); creationInterface->processCodeValuePair( groupCode, groupValue ); line += 2; processDXFGroup( creationInterface, groupCode, groupValue ); } return !feof( fp ); } /** * Same as above but for input streams. */ bool DL_Dxf::readDxfGroups( std::istream& 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, false ) ) { groupCode = (unsigned int) 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, bool stripSpace ) { 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, stripSpace ); s = line; assert( size > s.length() ); } delete[] wholeLine; // Done with wholeLine return true; } else { s = ""; return false; } } /** * Same as above but for input streams. */ bool DL_Dxf::getStrippedLine( std::string& s, unsigned int size, std::istream& stream, bool stripSpace ) { 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, stripSpace ); 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, bool stripSpace ) { // last non-NULL char: int lastChar = strlen( *s ) - 1; // Is last character CR or LF? while( (lastChar >= 0) && ( ( (*s)[lastChar] == 10 ) || ( (*s)[lastChar] == 13 ) || ( stripSpace && ( (*s)[lastChar] == ' ' || ( (*s)[lastChar] == '\t' ) ) ) ) ) { (*s)[lastChar] = '\0'; lastChar--; } // Skip whitespace, excluding \n, at beginning of line if( stripSpace ) { 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 agroupCode Constant indicating the data type of the group. * @param agroupValue 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 agroupCode, const std::string& agroupValue ) { // printf("%d\n", agroupCode); // printf("%s\n", agroupValue.c_str()); // Init values on first call if( firstCall ) { settingValue[0] = '\0'; firstCall = false; } // Indicates comment or dxflib version: if( agroupCode==999 ) { if( !agroupValue.empty() ) { if( agroupValue.substr( 0, 6 )=="dxflib" ) { libVersion = getLibVersion( agroupValue.substr( 7 ) ); } addComment( creationInterface, agroupValue ); } } // Indicates start of new entity or variable: else if( agroupCode==0 || agroupCode==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 = getInt16Value( 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( (bool) 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_ARCALIGNEDTEXT: addArcAlignedText( 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 ), getRealValue( 39, 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 ), getRealValue( 38, 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 ), getRealValue( 40, 0.0 ), getRealValue( 41, 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 stored in rad): 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!=NULL ) { delete[] vertices; } vertices = new double[4 * maxVertices]; for( int i = 0; i=0 && vertexIndex= 0 ) { vertices[4 * vertexIndex + 3] = toReal( groupValue ); } return true; } return false; } /** * Handles additional spline data. */ bool DL_Dxf::handleSplineData( DL_CreationInterface* /*creationInterface*/ ) { // Allocate Spline knots (group code 72): if( groupCode==72 ) { maxKnots = toInt( groupValue ); if( maxKnots>0 ) { if( knots!=NULL ) { delete[] knots; } knots = new double[maxKnots]; for( int i = 0; i0 ) { if( controlPoints!=NULL ) { delete[] controlPoints; } if( weights!=NULL ) { delete[] weights; } controlPoints = new double[3 * maxControlPoints]; weights = new double[maxControlPoints]; for( int i = 0; i0 ) { if( fitPoints!=NULL ) { delete[] fitPoints; } fitPoints = new double[3 * maxFitPoints]; for( int i = 0; i=0 && controlPointIndex=0 && fitPointIndex=0 && weightIndex0 ) { if( leaderVertices!=NULL ) { delete[] leaderVertices; } leaderVertices = new double[3 * maxLeaderVertices]; for( int i = 0; i=0 && leaderVertexIndexaddText( d ); } /** * Adds an arc aligned text entity that was read from the file via the creation interface. */ void DL_Dxf::addArcAlignedText( DL_CreationInterface* creationInterface ) { DL_ArcAlignedTextData d; d.text = getStringValue( 1, "" ); d.font = getStringValue( 2, "" ); d.style = getStringValue( 7, "" ); d.cx = getRealValue( 10, 0.0 ); d.cy = getRealValue( 20, 0.0 ); d.cz = getRealValue( 30, 0.0 ); d.radius = getRealValue( 40, 0.0 ); d.xScaleFactor = getRealValue( 41, 0.0 ); d.height = getRealValue( 42, 0.0 ); d.spacing = getRealValue( 43, 0.0 ); d.offset = getRealValue( 44, 0.0 ); d.rightOffset = getRealValue( 45, 0.0 ); d.leftOffset = getRealValue( 46, 0.0 ); d.startAngle = getRealValue( 50, 0.0 ); d.endAngle = getRealValue( 51, 0.0 ); d.reversedCharacterOrder = getIntValue( 70, 0 ); d.direction = getIntValue( 71, 0 ); d.alignment = getIntValue( 72, 0 ); d.side = getIntValue( 73, 0 ); d.bold = getIntValue( 74, 0 ); d.italic = getIntValue( 75, 0 ); d.underline = getIntValue( 76, 0 ); d.characerSet = getIntValue( 77, 0 ); d.pitch = getIntValue( 78, 0 ); d.shxFont = getIntValue( 79, 0 ); d.wizard = getIntValue( 280, 0 ); d.arcHandle = getIntValue( 330, 0 ); creationInterface->addArcAlignedText( 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: DL_DimensionData ret( // 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 ) ); ret.arrow1Flipped = getIntValue( 74, 0 ) == 1; ret.arrow2Flipped = getIntValue( 75, 0 ) == 1; return ret; } /** * 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_DimAngular2LData 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.emplace_back( ); } 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.emplace_back( ); 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; } } 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; } } // 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 = (bool) toInt( groupValue ); hatchEdge.defined = true; return true; } } // 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 = (bool) toInt( groupValue ); hatchEdge.defined = true; return true; } } // 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; } } } 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 aVersion ) { char* f = new char[strlen( file ) + 1]; strcpy( f, file ); this->version = aVersion; DL_WriterA* dw = new DL_WriterA( f, aVersion ); 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; case DL_Codes::AC1009_MIN: // minimalistic DXF version is unidentified in file: 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 aAttrib Attributes */ void DL_Dxf::writePoint( DL_WriterA& dw, const DL_PointData& data, const DL_Attributes& aAttrib ) { dw.entity( "POINT" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbPoint" ); } 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 aAttrib Attributes */ void DL_Dxf::writeLine( DL_WriterA& dw, const DL_LineData& data, const DL_Attributes& aAttrib ) { dw.entity( "LINE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbLine" ); } 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 aAttrib Attributes */ void DL_Dxf::writeXLine( DL_WriterA& dw, const DL_XLineData& data, const DL_Attributes& aAttrib ) { dw.entity( "XLINE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbLine" ); } 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 aAttrib Attributes */ void DL_Dxf::writeRay( DL_WriterA& dw, const DL_RayData& data, const DL_Attributes& aAttrib ) { dw.entity( "RAY" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbLine" ); } 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 aAttrib Attributes * @see writeVertex */ void DL_Dxf::writePolyline( DL_WriterA& dw, const DL_PolylineData& data, const DL_Attributes& aAttrib ) { if( version==DL_VERSION_2000 ) { dw.entity( "LWPOLYLINE" ); dw.dxfString( 100, "AcDbEntity" ); dw.entityAttributes( attrib ); dw.dxfString( 100, "AcDbPolyline" ); dw.dxfInt( 90, (int) 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 aAttrib 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 ); if( fabs( data.bulge )>1.0e-10 ) { dw.dxfReal( 42, data.bulge ); } } else { dw.entity( "VERTEX" ); // dw.entityAttributes(aAttrib); 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 aAttrib Attributes * @see writeControlPoint */ void DL_Dxf::writeSpline( DL_WriterA& dw, const DL_SplineData& data, const DL_Attributes& aAttrib ) { dw.entity( "SPLINE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { 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 aAttrib 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 */ 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 */ 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 aAttrib Attributes */ void DL_Dxf::writeCircle( DL_WriterA& dw, const DL_CircleData& data, const DL_Attributes& aAttrib ) { dw.entity( "CIRCLE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbCircle" ); } 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 aAttrib Attributes */ void DL_Dxf::writeArc( DL_WriterA& dw, const DL_ArcData& data, const DL_Attributes& aAttrib ) { dw.entity( "ARC" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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 aAttrib Attributes */ void DL_Dxf::writeEllipse( DL_WriterA& dw, const DL_EllipseData& data, const DL_Attributes& aAttrib ) { if( version>DL_VERSION_R12 ) { dw.entity( "ELLIPSE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEllipse" ); } 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 aAttrib Attributes */ void DL_Dxf::writeSolid( DL_WriterA& dw, const DL_SolidData& data, const DL_Attributes& aAttrib ) { dw.entity( "SOLID" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbTrace" ); } 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 aAttrib Attributes */ void DL_Dxf::writeTrace( DL_WriterA& dw, const DL_TraceData& data, const DL_Attributes& aAttrib ) { dw.entity( "TRACE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbTrace" ); } 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 aAttrib Attributes */ void DL_Dxf::write3dFace( DL_WriterA& dw, const DL_3dFaceData& data, const DL_Attributes& aAttrib ) { dw.entity( "3DFACE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbFace" ); } 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 aAttrib Attributes */ void DL_Dxf::writeInsert( DL_WriterA& dw, const DL_InsertData& data, const DL_Attributes& aAttrib ) { 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.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { if( data.cols!=1 || data.rows!=1 ) { dw.dxfString( 100, "AcDbMInsertBlock" ); } else { dw.dxfString( 100, "AcDbBlockReference" ); } } dw.dxfString( 2, data.name ); dw.dxfReal( 10, data.ipx ); dw.dxfReal( 20, data.ipy ); dw.dxfReal( 30, data.ipz ); if( data.sx!=1.0 || data.sy!=1.0 ) { dw.dxfReal( 41, data.sx ); dw.dxfReal( 42, data.sy ); dw.dxfReal( 43, 1.0 ); } if( 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( data.colSp!=0.0 || 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 aAttrib Attributes */ void DL_Dxf::writeMText( DL_WriterA& dw, const DL_MTextData& data, const DL_Attributes& aAttrib ) { dw.entity( "MTEXT" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbMText" ); } 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: #define TEXT_CHUNK_SIZE 250 std::size_t length = data.text.length(); char chunk[TEXT_CHUNK_SIZE+1]; std::size_t i = 0; for( i = TEXT_CHUNK_SIZE; i < length; i += TEXT_CHUNK_SIZE ) { strncpy( chunk, &data.text.c_str()[i - TEXT_CHUNK_SIZE], TEXT_CHUNK_SIZE ); chunk[TEXT_CHUNK_SIZE] = '\0'; dw.dxfString( 3, chunk ); } strncpy( chunk, &data.text.c_str()[i - TEXT_CHUNK_SIZE], TEXT_CHUNK_SIZE ); chunk[TEXT_CHUNK_SIZE] = '\0'; dw.dxfString( 1, chunk ); dw.dxfString( 7, data.style ); // since dxflib 2.0.2.1: degrees not rad (error in autodesk dxf doc) dw.dxfReal( 50, data.angle / (2.0 * M_PI) * 360.0 ); dw.dxfInt( 73, data.lineSpacingStyle ); dw.dxfReal( 44, data.lineSpacingFactor ); } /** * Writes a text entity to the file. * * @param dw DXF writer * @param data Entity data from the file * @param aAttrib Attributes */ void DL_Dxf::writeText( DL_WriterA& dw, const DL_TextData& data, const DL_Attributes& aAttrib ) { dw.entity( "TEXT" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbText" ); } dw.dxfReal( 10, data.ipx ); dw.dxfReal( 20, data.ipy ); dw.dxfReal( 30, data.ipz ); dw.dxfReal( 40, data.height ); dw.dxfString( 1, data.text ); dw.dxfReal( 50, data.angle / (2 * M_PI) * 360.0 ); dw.dxfReal( 41, data.xScaleFactor ); dw.dxfString( 7, data.style ); dw.dxfInt( 71, data.textGenerationFlags ); dw.dxfInt( 72, data.hJustification ); dw.dxfReal( 11, data.apx ); dw.dxfReal( 21, data.apy ); dw.dxfReal( 31, data.apz ); if( version==DL_VERSION_2000 ) { // required twice for some reason: dw.dxfString( 100, "AcDbText" ); } dw.dxfInt( 73, data.vJustification ); } void DL_Dxf::writeAttribute( DL_WriterA& dw, const DL_AttributeData& data, const DL_Attributes& aAttrib ) { dw.entity( "ATTRIB" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbText" ); } dw.dxfReal( 10, data.ipx ); dw.dxfReal( 20, data.ipy ); dw.dxfReal( 30, data.ipz ); dw.dxfReal( 40, data.height ); dw.dxfString( 1, data.text ); dw.dxfReal( 50, data.angle / (2 * M_PI) * 360.0 ); dw.dxfReal( 41, data.xScaleFactor ); dw.dxfString( 7, data.style ); dw.dxfInt( 71, data.textGenerationFlags ); dw.dxfInt( 72, data.hJustification ); dw.dxfReal( 11, data.apx ); dw.dxfReal( 21, data.apy ); dw.dxfReal( 31, data.apz ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbAttribute" ); } dw.dxfString( 2, data.tag ); dw.dxfInt( 74, data.vJustification ); } void DL_Dxf::writeDimStyleOverrides( DL_WriterA& dw, const DL_DimensionData& data ) { if( version==DL_VERSION_2000 ) { dw.dxfString( 1001, "ACAD" ); dw.dxfString( 1000, "DSTYLE" ); dw.dxfString( 1002, "{" ); if( data.type & 128 ) { // custom text position: dw.dxfInt( 1070, 279 ); dw.dxfInt( 1070, 2 ); } dw.dxfInt( 1070, 144 ); dw.dxfReal( 1040, data.linearFactor ); dw.dxfInt( 1070, 40 ); dw.dxfReal( 1040, data.dimScale ); 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 aAttrib Attributes */ void DL_Dxf::writeDimAligned( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAlignedData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); dw.dxfInt( 75, data.arrow2Flipped ); 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 aAttrib Attributes */ void DL_Dxf::writeDimLinear( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimLinearData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); dw.dxfInt( 75, data.arrow2Flipped ); 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 aAttrib Attributes */ void DL_Dxf::writeDimRadial( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimRadialData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); //dw.dxfInt(75, data.arrow2Flipped); 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 aAttrib Attributes */ void DL_Dxf::writeDimDiametric( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimDiametricData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); dw.dxfInt( 75, data.arrow2Flipped ); 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 aAttrib Attributes */ void DL_Dxf::writeDimAngular2L( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAngular2LData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); dw.dxfInt( 75, data.arrow2Flipped ); 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 aAttrib Attributes */ void DL_Dxf::writeDimAngular3P( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimAngular3PData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt( 74, data.arrow1Flipped ); dw.dxfInt( 75, data.arrow2Flipped ); 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 aAttrib Attributes */ void DL_Dxf::writeDimOrdinate( DL_WriterA& dw, const DL_DimensionData& data, const DL_DimOrdinateData& edata, const DL_Attributes& aAttrib ) { dw.entity( "DIMENSION" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); 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.dxfInt(74, data.arrow1Flipped); //dw.dxfInt(75, data.arrow2Flipped); 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 aAttrib Attributes * @see writeVertex */ void DL_Dxf::writeLeader( DL_WriterA& dw, const DL_LeaderData& data, const DL_Attributes& aAttrib ) { if( version>DL_VERSION_R12 ) { dw.entity( "LEADER" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { 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 ); } } void DL_Dxf::writeLeaderEnd( DL_WriterA& dw, const DL_LeaderData& data ) { if( version == DL_VERSION_2000 ) { dw.dxfString( 1001, "ACAD" ); dw.dxfString( 1000, "DSTYLE" ); dw.dxfString( 1002, "{" ); dw.dxfInt( 1070, 40 ); dw.dxfReal( 1040, data.dimScale ); dw.dxfString( 1002, "}" ); } } /** * 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 aAttrib Attributes */ void DL_Dxf::writeHatch1( DL_WriterA& dw, const DL_HatchData& data, const DL_Attributes& aAttrib ) { dw.entity( "HATCH" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { 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, (int) 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 aAttrib Attributes */ void DL_Dxf::writeHatch2( DL_WriterA& dw, const DL_HatchData& data, const DL_Attributes& /*aAttrib*/ ) { 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 ); } } /** * 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. */ 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. */ 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. */ 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, (int) (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, (int) (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. */ unsigned int DL_Dxf::writeImage( DL_WriterA& dw, const DL_ImageData& data, const DL_Attributes& aAttrib ) { /*if (data.file.empty()) { * std::cerr << "DL_Dxf::writeImage: " * << "Image file must not be empty\n"; * return; * }*/ dw.entity( "IMAGE" ); if( version==DL_VERSION_2000 ) { dw.dxfString( 100, "AcDbEntity" ); } dw.entityAttributes( aAttrib ); if( version==DL_VERSION_2000 ) { 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 unsigned int handle = dw.handle(340); // 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 aAttrib Attributes */ void DL_Dxf::writeLayer( DL_WriterA& dw, const DL_LayerData& data, const DL_Attributes& aAttrib ) { if( data.name.empty() ) { std::cerr << "DL_Dxf::writeLayer: " << "Layer name must not be empty\n"; return; } int color = aAttrib.getColor(); if( color>=256 ) { std::cerr << "Layer color cannot be " << color << ". Changed to 7.\n"; color = 7; } if( data.off ) { // negative color value means layer is off: color = -color; } 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 && aAttrib.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, int dimtad, bool dimtih ) { 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 ); } // DIMTIH: dw.dxfInt( 73, (int) dimtih ); dw.dxfInt( 74, 0 ); if( version==DL_VERSION_R12 ) { dw.dxfInt( 75, 0 ); dw.dxfInt( 76, 0 ); } // DIMTAD: dw.dxfInt( 77, dimtad ); 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, 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 = 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, dw.getNextHandle() + 1 ); // 2E dw.dxfString( 3, "HIDETEXT" ); // dw.dxfHex(350, 0x2E); dw.dxfHex( 350, 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, appDictionaryHandle ); dw.dxfString( 100, "AcDbDictionary" ); dw.dxfInt( 281, 1 ); } unsigned int DL_Dxf::writeDictionaryEntry( DL_WriterA& dw, const std::string& name ) { dw.dxfString( 3, name ); return dw.handle(350); } void DL_Dxf::writeXRecord( DL_WriterA& dw, int handle, int value ) { dw.dxfString( 0, "XRECORD" ); dw.dxfHex( 5, handle ); dw.dxfHex( 330, 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, 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, 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, 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 ) { std::size_t 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] = 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"; delete[] buf1; delete[] buf2; delete[] buf3; delete[] buf4; delete[] buf5; delete[] buf6; }