valentina_old/src/libs/vdxf/dxflib/dl_dxf.cpp
Valentina Zhuravska 0b16f5acf0 Fixed "comparing floating point with == is unsafe"
--HG--
branch : feature
2015-10-02 05:46:10 +03:00

5944 lines
144 KiB
C++

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