COMPASSi/trunk/code/projects/ReadDXF/dl_dxf.cpp

5276 lines
139 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 <cstring>
#include <iostream>
#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;
vertices = NULL;
maxVertices = 0;
vertexIndex = 0;
knots = NULL;
maxKnots = 0;
knotIndex = 0;
weights = NULL;
weightIndex = 0;
controlPoints = NULL;
maxControlPoints = 0;
controlPointIndex = 0;
fitPoints = NULL;
maxFitPoints = 0;
fitPointIndex = 0;
leaderVertices = NULL;
maxLeaderVertices = 0;
leaderVertexIndex = 0;
}
/**
* Destructor.
*/
DL_Dxf::~DL_Dxf() {
if (vertices!=NULL) {
delete[] vertices;
}
if (knots!=NULL) {
delete[] knots;
}
if (controlPoints!=NULL) {
delete[] controlPoints;
}
if (fitPoints!=NULL) {
delete[] fitPoints;
}
if (weights!=NULL) {
delete[] weights;
}
if (leaderVertices!=NULL) {
delete[] leaderVertices;
}
}
/**
* @brief Reads the given file and calls the appropriate functions in
* the given creation interface for every entity found in the file.
*
* @param file Input
* 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");
//fp = fopen("d:/simple_line.dxf", "rt");
if (fp) {
while (readDxfGroups(fp, creationInterface)) {}
fclose(fp);
return true;
}
return false;
}
bool DL_Dxf::in(const std::wstring& file, DL_CreationInterface* creationInterface)
{
//std::string kapth = "D:/内河/bin/Data/XF/50m.igs";
#ifdef _WIN32
FILE *fp;
bool firstCall = true;
int currentObjectType = DL_UNKNOWN;
// Open the file using _wfopen
fp = _wfopen(file.c_str(), L"rt");
if (fp) {
while (readDxfGroups(fp, creationInterface)) {}
fclose(fp);
return true;
} else {
return false;
}
#endif
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, false) ) {
groupCode = (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, false) ) {
groupCode = (unsigned int)toInt(groupCodeTmp);
line+=2;
processDXFGroup(creationInterface, groupCode, groupValue);
}
return !stream.eof();
}
/**
* @brief Reads line from file & strips whitespace at start and newline
* at end.
*
* @param s Output\n
* Pointer to character array that chopped line will be returned in.
* @param size Size of \p s. (Including space for NULL.)
* @param fp Input\n
* Handle of input file.
*
* @retval true if line could be read
* @retval false if \p fp is already at end of file
*
* @todo Change function to use safer FreeBSD strl* functions
* @todo Is it a problem if line is blank (i.e., newline only)?
* Then, when function returns, (s==NULL).
*/
bool DL_Dxf::getStrippedLine(std::string& s, unsigned int size, FILE *fp, bool stripSpace) {
if (!feof(fp)) {
// The whole line in the file. Includes space for NULL.
char* wholeLine = new char[size];
// Only the useful part of the line
char* line;
line = fgets(wholeLine, size, fp);
if (line!=NULL && line[0] != '\0') { // Evaluates to fgets() retval
// line == wholeLine at this point.
// Both guaranteed to be NULL terminated.
// Strip leading whitespace and trailing CR/LF.
stripWhiteSpace(&line, stripSpace);
s = line;
assert(size > s.length());
}
delete[] wholeLine; // Done with wholeLine
return true;
} else {
s = "";
return false;
}
}
/**
* Same as above but for stringstreams.
*/
bool DL_Dxf::getStrippedLine(std::string &s, unsigned int size,
std::stringstream& stream, bool stripSpace) {
if (!stream.eof()) {
// Only the useful part of the line
char* line = new char[size+1];
char* oriLine = line;
stream.getline(line, size);
stripWhiteSpace(&line, stripSpace);
s = line;
assert(size > s.length());
delete[] oriLine;
return true;
} else {
s[0] = '\0';
return false;
}
}
/**
* @brief Strips leading whitespace and trailing Carriage Return (CR)
* and Line Feed (LF) from NULL terminated string.
*
* @param s Input and output.
* NULL terminates string.
*
* @retval true if \p s is non-NULL
* @retval false if \p s is NULL
*/
bool DL_Dxf::stripWhiteSpace(char** s, bool stripSpace) {
// last non-NULL char:
int lastChar = strlen(*s) - 1;
// Is last character CR or LF?
while ( (lastChar >= 0) &&
(((*s)[lastChar] == 10) || ((*s)[lastChar] == 13) ||
(stripSpace && ((*s)[lastChar] == ' ' || ((*s)[lastChar] == '\t')))) ) {
(*s)[lastChar] = '\0';
lastChar--;
}
// Skip whitespace, excluding \n, at beginning of line
if (stripSpace) {
while ((*s)[0]==' ' || (*s)[0]=='\t') {
++(*s);
}
}
return ((*s) ? true : false);
}
/**
* Processes a group (pair of group code and value).
*
* @param creationInterface Handle to class that creates entities and
* other CAD data from DXF group codes
*
* @param 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((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!=NULL) {
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!=NULL) {
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!=NULL) {
delete[] controlPoints;
}
if (weights!=NULL) {
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!=NULL) {
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!=NULL) {
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, DL_NANDOUBLE),
getRealValue(21, DL_NANDOUBLE),
getRealValue(31, DL_NANDOUBLE),
// 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(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;
}
}
else {
// Line edge:
if (hatchEdge.type==1) {
switch (groupCode) {
case 10:
hatchEdge.x1 = toReal(groupValue);
return true;
case 20:
hatchEdge.y1 = toReal(groupValue);
return true;
case 11:
hatchEdge.x2 = toReal(groupValue);
return true;
case 21:
hatchEdge.y2 = toReal(groupValue);
hatchEdge.defined = true;
return true;
}
}
// Arc edge:
if (hatchEdge.type==2) {
switch(groupCode) {
case 10:
hatchEdge.cx = toReal(groupValue);
return true;
case 20:
hatchEdge.cy = toReal(groupValue);
return true;
case 40:
hatchEdge.radius = toReal(groupValue);
return true;
case 50:
hatchEdge.angle1 = toReal(groupValue)/360.0*2*M_PI;
return true;
case 51:
hatchEdge.angle2 = toReal(groupValue)/360.0*2*M_PI;
return true;
case 73:
hatchEdge.ccw = (bool)toInt(groupValue);
hatchEdge.defined = true;
return true;
}
}
// Ellipse arc edge:
if (hatchEdge.type==3) {
switch (groupCode) {
case 10:
hatchEdge.cx = toReal(groupValue);
return true;
case 20:
hatchEdge.cy = toReal(groupValue);
return true;
case 11:
hatchEdge.mx = toReal(groupValue);
return true;
case 21:
hatchEdge.my = toReal(groupValue);
return true;
case 40:
hatchEdge.ratio = toReal(groupValue);
return true;
case 50:
hatchEdge.angle1 = toReal(groupValue)/360.0*2*M_PI;
return true;
case 51:
hatchEdge.angle2 = toReal(groupValue)/360.0*2*M_PI;
return true;
case 73:
hatchEdge.ccw = (bool)toInt(groupValue);
hatchEdge.defined = true;
return true;
}
}
// Spline edge:
if (hatchEdge.type==4) {
switch (groupCode) {
case 94:
hatchEdge.degree = toInt(groupValue);
return true;
case 73:
hatchEdge.rational = toBool(groupValue);
return true;
case 74:
hatchEdge.periodic = toBool(groupValue);
return true;
case 95:
hatchEdge.nKnots = toInt(groupValue);
return true;
case 96:
hatchEdge.nControl = toInt(groupValue);
return true;
case 97:
hatchEdge.nFit = toInt(groupValue);
return true;
case 40:
if (hatchEdge.knots.size() < hatchEdge.nKnots) {
hatchEdge.knots.push_back(toReal(groupValue));
}
return true;
case 10:
if (hatchEdge.controlPoints.size() < hatchEdge.nControl) {
std::vector<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;
}
}
}
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];
std::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;
case DL_Codes::AC1009_MIN:
// minimalistic DXF version is unidentified in file:
break;
}
// Newer version require that (otherwise a*cad crashes..)
if (version==DL_VERSION_2000) {
dw.dxfString(9, "$HANDSEED");
dw.dxfHex(5, 0xFFFF);
}
// commented out: more variables can be added after that by caller:
//dw.sectionEnd();
}
/**
* Writes a point entity to the file.
*
* @param dw DXF writer
* @param data Entity data from the file
* @param 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, (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");
if (data.cols!=1 || data.rows!=1) {
dw.dxfString(100, "AcDbMInsertBlock");
}
else {
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 (data.sx!=1.0 || data.sy!=1.0) {
dw.dxfReal(41, data.sx);
dw.dxfReal(42, data.sy);
dw.dxfReal(43, 1.0);
}
if (data.angle!=0.0) {
dw.dxfReal(50, data.angle);
}
if (data.cols!=1 || data.rows!=1) {
dw.dxfInt(70, data.cols);
dw.dxfInt(71, data.rows);
}
if (data.colSp!=0.0 || data.rowSp!=0.0) {
dw.dxfReal(44, data.colSp);
dw.dxfReal(45, data.rowSp);
}
}
/**
* Writes a multi text entity to the file.
*
* @param dw DXF writer
* @param data Entity data from the file
* @param 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 = data.text.length();
char chunk[251];
int i;
for (i=250; i<length; i+=250) {
std::strncpy(chunk, &data.text.c_str()[i-250], 250);
chunk[250]='\0';
dw.dxfString(3, chunk);
}
std::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.dxfReal(1040, data.linearFactor);
dw.dxfInt(1070,40);
dw.dxfReal(1040, data.dimScale);
dw.dxfString(1002, "}");
}
}
/**
* Writes an aligned dimension entity to the file.
*
* @param dw DXF writer
* @param data Generic dimension data for from the file
* @param data Specific aligned dimension data from the file
* @param 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, (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, (int)(data.ccw));
break;
// ellipse arc:
case 3:
dw.dxfReal(10, data.cx);
dw.dxfReal(20, data.cy);
dw.dxfReal(11, data.mx);
dw.dxfReal(21, data.my);
dw.dxfReal(40, data.ratio);
dw.dxfReal(50, data.angle1/(2*M_PI)*360.0);
dw.dxfReal(51, data.angle2/(2*M_PI)*360.0);
dw.dxfInt(73, (int)(data.ccw));
break;
// spline:
case 4:
dw.dxfInt(94, data.degree);
dw.dxfBool(73, data.rational);
dw.dxfBool(74, data.periodic);
dw.dxfInt(95, data.nKnots);
dw.dxfInt(96, data.nControl);
for (unsigned int i=0; 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 = 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, styleHandleStd);
//dw.dxfHex(340, 0x11);
}
// * /
dw.dxfString( 0, "ENDTAB");
}
/**
* Writes a blockrecord section. This section is needed in DL_VERSION_R13.
* Note that this method currently only writes a faked BLOCKRECORD section
* to make the file readable by Aut*cad.
*/
void DL_Dxf::writeBlockRecord(DL_WriterA& dw) {
dw.dxfString( 0, "TABLE");
dw.dxfString( 2, "BLOCK_RECORD");
if (version==DL_VERSION_2000) {
dw.dxfHex(5, 1);
}
//dw.dxfHex(330, 0);
if (version==DL_VERSION_2000) {
dw.dxfString(100, "AcDbSymbolTable");
}
dw.dxfInt( 70, 1);
dw.dxfString( 0, "BLOCK_RECORD");
if (version==DL_VERSION_2000) {
dw.dxfHex(5, 0x1F);
}
//int msh = dw.handle();
//dw.setModelSpaceHandle(msh);
//dw.dxfHex(330, 1);
if (version==DL_VERSION_2000) {
dw.dxfString(100, "AcDbSymbolTableRecord");
dw.dxfString(100, "AcDbBlockTableRecord");
}
dw.dxfString( 2, "*Model_Space");
dw.dxfHex(340, 0x22);
dw.dxfString( 0, "BLOCK_RECORD");
if (version==DL_VERSION_2000) {
dw.dxfHex(5, 0x1B);
}
//int psh = dw.handle();
//dw.setPaperSpaceHandle(psh);
//dw.dxfHex(330, 1);
if (version==DL_VERSION_2000) {
dw.dxfString(100, "AcDbSymbolTableRecord");
dw.dxfString(100, "AcDbBlockTableRecord");
}
dw.dxfString( 2, "*Paper_Space");
dw.dxfHex(340, 0x1E);
dw.dxfString( 0, "BLOCK_RECORD");
if (version==DL_VERSION_2000) {
dw.dxfHex(5, 0x23);
}
//int ps0h = dw.handle();
//dw.setPaperSpace0Handle(ps0h);
//dw.dxfHex(330, 1);
if (version==DL_VERSION_2000) {
dw.dxfString(100, "AcDbSymbolTableRecord");
dw.dxfString(100, "AcDbBlockTableRecord");
}
dw.dxfString( 2, "*Paper_Space0");
dw.dxfHex(340, 0x26);
//dw.dxfString( 0, "ENDTAB");
}
/**
* Writes a single block record with the given name.
*/
void DL_Dxf::writeBlockRecord(DL_WriterA& dw, const std::string& name) {
dw.dxfString( 0, "BLOCK_RECORD");
if (version==DL_VERSION_2000) {
dw.handle();
}
//dw->dxfHex(330, 1);
if (version==DL_VERSION_2000) {
dw.dxfString(100, "AcDbSymbolTableRecord");
dw.dxfString(100, "AcDbBlockTableRecord");
}
dw.dxfString( 2, name);
dw.dxfHex(340, 0);
}
/**
* Writes a objects section. This section is needed in DL_VERSION_R13.
* Note that this method currently only writes a faked OBJECTS section
* to make the file readable by Aut*cad.
*/
void DL_Dxf::writeObjects(DL_WriterA& dw, const std::string& appDictionaryName) {
dw.dxfString( 0, "SECTION");
dw.dxfString( 2, "OBJECTS");
dw.dxfString( 0, "DICTIONARY");
dw.dxfHex(5, 0xC);
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(280, 0);
dw.dxfInt(281, 1);
dw.dxfString( 3, "ACAD_GROUP");
dw.dxfHex(350, 0xD);
dw.dxfString( 3, "ACAD_LAYOUT");
dw.dxfHex(350, 0x1A);
dw.dxfString( 3, "ACAD_MLINESTYLE");
dw.dxfHex(350, 0x17);
dw.dxfString( 3, "ACAD_PLOTSETTINGS");
dw.dxfHex(350, 0x19);
dw.dxfString( 3, "ACAD_PLOTSTYLENAME");
dw.dxfHex(350, 0xE);
dw.dxfString( 3, "AcDbVariableDictionary");
int acDbVariableDictionaryHandle = dw.handle(350);
//int acDbVariableDictionaryHandle = dw.getNextHandle();
//dw.dxfHex(350, acDbVariableDictionaryHandle);
//dw.incHandle();
if (appDictionaryName.length()!=0) {
dw.dxfString( 3, appDictionaryName);
appDictionaryHandle = dw.handle(350);
//appDictionaryHandle = dw.getNextHandle();
//dw.dxfHex(350, appDictionaryHandle);
//dw.incHandle();
}
dw.dxfString( 0, "DICTIONARY");
dw.dxfHex(5, 0xD);
//dw.handle(); // D
//dw.dxfHex(330, 0xC);
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(280, 0);
dw.dxfInt(281, 1);
dw.dxfString( 0, "ACDBDICTIONARYWDFLT");
dw.dxfHex(5, 0xE);
//dicId4 = dw.handle(); // E
//dw.dxfHex(330, 0xC); // C
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(281, 1);
dw.dxfString( 3, "Normal");
dw.dxfHex(350, 0xF);
//dw.dxfHex(350, dw.getNextHandle()+5); // F
dw.dxfString(100, "AcDbDictionaryWithDefault");
dw.dxfHex(340, 0xF);
//dw.dxfHex(340, dw.getNextHandle()+5); // F
dw.dxfString( 0, "ACDBPLACEHOLDER");
dw.dxfHex(5, 0xF);
//dw.handle(); // F
//dw.dxfHex(330, dicId4); // E
dw.dxfString( 0, "DICTIONARY");
//dicId3 = dw.handle(); // 17
dw.dxfHex(5, 0x17);
//dw.dxfHex(330, 0xC); // C
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(280, 0);
dw.dxfInt(281, 1);
dw.dxfString( 3, "Standard");
dw.dxfHex(350, 0x18);
//dw.dxfHex(350, dw.getNextHandle()+5); // 18
dw.dxfString( 0, "MLINESTYLE");
dw.dxfHex(5, 0x18);
//dw.handle(); // 18
//dw.dxfHex(330, dicId3); // 17
dw.dxfString(100, "AcDbMlineStyle");
dw.dxfString( 2, "STANDARD");
dw.dxfInt( 70, 0);
dw.dxfString( 3, "");
dw.dxfInt( 62, 256);
dw.dxfReal( 51, 90.0);
dw.dxfReal( 52, 90.0);
dw.dxfInt( 71, 2);
dw.dxfReal( 49, 0.5);
dw.dxfInt( 62, 256);
dw.dxfString( 6, "BYLAYER");
dw.dxfReal( 49, -0.5);
dw.dxfInt( 62, 256);
dw.dxfString( 6, "BYLAYER");
dw.dxfString( 0, "DICTIONARY");
dw.dxfHex(5, 0x19);
//dw.handle(); // 17
//dw.dxfHex(330, 0xC); // C
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(280, 0);
dw.dxfInt(281, 1);
dw.dxfString( 0, "DICTIONARY");
//dicId2 = dw.handle(); // 1A
dw.dxfHex(5, 0x1A);
//dw.dxfHex(330, 0xC);
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(281, 1);
dw.dxfString( 3, "Layout1");
dw.dxfHex(350, 0x1E);
//dw.dxfHex(350, dw.getNextHandle()+2); // 1E
dw.dxfString( 3, "Layout2");
dw.dxfHex(350, 0x26);
//dw.dxfHex(350, dw.getNextHandle()+4); // 26
dw.dxfString( 3, "Model");
dw.dxfHex(350, 0x22);
//dw.dxfHex(350, dw.getNextHandle()+5); // 22
dw.dxfString( 0, "LAYOUT");
dw.dxfHex(5, 0x1E);
//dw.handle(); // 1E
//dw.dxfHex(330, dicId2); // 1A
dw.dxfString(100, "AcDbPlotSettings");
dw.dxfString( 1, "");
dw.dxfString( 2, "none_device");
dw.dxfString( 4, "");
dw.dxfString( 6, "");
dw.dxfReal( 40, 0.0);
dw.dxfReal( 41, 0.0);
dw.dxfReal( 42, 0.0);
dw.dxfReal( 43, 0.0);
dw.dxfReal( 44, 0.0);
dw.dxfReal( 45, 0.0);
dw.dxfReal( 46, 0.0);
dw.dxfReal( 47, 0.0);
dw.dxfReal( 48, 0.0);
dw.dxfReal( 49, 0.0);
dw.dxfReal(140, 0.0);
dw.dxfReal(141, 0.0);
dw.dxfReal(142, 1.0);
dw.dxfReal(143, 1.0);
dw.dxfInt( 70, 688);
dw.dxfInt( 72, 0);
dw.dxfInt( 73, 0);
dw.dxfInt( 74, 5);
dw.dxfString( 7, "");
dw.dxfInt( 75, 16);
dw.dxfReal(147, 1.0);
dw.dxfReal(148, 0.0);
dw.dxfReal(149, 0.0);
dw.dxfString(100, "AcDbLayout");
dw.dxfString( 1, "Layout1");
dw.dxfInt( 70, 1);
dw.dxfInt( 71, 1);
dw.dxfReal( 10, 0.0);
dw.dxfReal( 20, 0.0);
dw.dxfReal( 11, 420.0);
dw.dxfReal( 21, 297.0);
dw.dxfReal( 12, 0.0);
dw.dxfReal( 22, 0.0);
dw.dxfReal( 32, 0.0);
dw.dxfReal( 14, 1.000000000000000E+20);
dw.dxfReal( 24, 1.000000000000000E+20);
dw.dxfReal( 34, 1.000000000000000E+20);
dw.dxfReal( 15, -1.000000000000000E+20);
dw.dxfReal( 25, -1.000000000000000E+20);
dw.dxfReal( 35, -1.000000000000000E+20);
dw.dxfReal(146, 0.0);
dw.dxfReal( 13, 0.0);
dw.dxfReal( 23, 0.0);
dw.dxfReal( 33, 0.0);
dw.dxfReal( 16, 1.0);
dw.dxfReal( 26, 0.0);
dw.dxfReal( 36, 0.0);
dw.dxfReal( 17, 0.0);
dw.dxfReal( 27, 1.0);
dw.dxfReal( 37, 0.0);
dw.dxfInt( 76, 0);
//dw.dxfHex(330, dw.getPaperSpaceHandle()); // 1B
dw.dxfHex(330, 0x1B);
dw.dxfString( 0, "LAYOUT");
dw.dxfHex(5, 0x22);
//dw.handle(); // 22
//dw.dxfHex(330, dicId2); // 1A
dw.dxfString(100, "AcDbPlotSettings");
dw.dxfString( 1, "");
dw.dxfString( 2, "none_device");
dw.dxfString( 4, "");
dw.dxfString( 6, "");
dw.dxfReal( 40, 0.0);
dw.dxfReal( 41, 0.0);
dw.dxfReal( 42, 0.0);
dw.dxfReal( 43, 0.0);
dw.dxfReal( 44, 0.0);
dw.dxfReal( 45, 0.0);
dw.dxfReal( 46, 0.0);
dw.dxfReal( 47, 0.0);
dw.dxfReal( 48, 0.0);
dw.dxfReal( 49, 0.0);
dw.dxfReal(140, 0.0);
dw.dxfReal(141, 0.0);
dw.dxfReal(142, 1.0);
dw.dxfReal(143, 1.0);
dw.dxfInt( 70, 1712);
dw.dxfInt( 72, 0);
dw.dxfInt( 73, 0);
dw.dxfInt( 74, 0);
dw.dxfString( 7, "");
dw.dxfInt( 75, 0);
dw.dxfReal(147, 1.0);
dw.dxfReal(148, 0.0);
dw.dxfReal(149, 0.0);
dw.dxfString(100, "AcDbLayout");
dw.dxfString( 1, "Model");
dw.dxfInt( 70, 1);
dw.dxfInt( 71, 0);
dw.dxfReal( 10, 0.0);
dw.dxfReal( 20, 0.0);
dw.dxfReal( 11, 12.0);
dw.dxfReal( 21, 9.0);
dw.dxfReal( 12, 0.0);
dw.dxfReal( 22, 0.0);
dw.dxfReal( 32, 0.0);
dw.dxfReal( 14, 0.0);
dw.dxfReal( 24, 0.0);
dw.dxfReal( 34, 0.0);
dw.dxfReal( 15, 0.0);
dw.dxfReal( 25, 0.0);
dw.dxfReal( 35, 0.0);
dw.dxfReal(146, 0.0);
dw.dxfReal( 13, 0.0);
dw.dxfReal( 23, 0.0);
dw.dxfReal( 33, 0.0);
dw.dxfReal( 16, 1.0);
dw.dxfReal( 26, 0.0);
dw.dxfReal( 36, 0.0);
dw.dxfReal( 17, 0.0);
dw.dxfReal( 27, 1.0);
dw.dxfReal( 37, 0.0);
dw.dxfInt( 76, 0);
//dw.dxfHex(330, dw.getModelSpaceHandle()); // 1F
dw.dxfHex(330, 0x1F);
dw.dxfString( 0, "LAYOUT");
//dw.handle(); // 26
dw.dxfHex(5, 0x26);
//dw.dxfHex(330, dicId2); // 1A
dw.dxfString(100, "AcDbPlotSettings");
dw.dxfString( 1, "");
dw.dxfString( 2, "none_device");
dw.dxfString( 4, "");
dw.dxfString( 6, "");
dw.dxfReal( 40, 0.0);
dw.dxfReal( 41, 0.0);
dw.dxfReal( 42, 0.0);
dw.dxfReal( 43, 0.0);
dw.dxfReal( 44, 0.0);
dw.dxfReal( 45, 0.0);
dw.dxfReal( 46, 0.0);
dw.dxfReal( 47, 0.0);
dw.dxfReal( 48, 0.0);
dw.dxfReal( 49, 0.0);
dw.dxfReal(140, 0.0);
dw.dxfReal(141, 0.0);
dw.dxfReal(142, 1.0);
dw.dxfReal(143, 1.0);
dw.dxfInt( 70, 688);
dw.dxfInt( 72, 0);
dw.dxfInt( 73, 0);
dw.dxfInt( 74, 5);
dw.dxfString( 7, "");
dw.dxfInt( 75, 16);
dw.dxfReal(147, 1.0);
dw.dxfReal(148, 0.0);
dw.dxfReal(149, 0.0);
dw.dxfString(100, "AcDbLayout");
dw.dxfString( 1, "Layout2");
dw.dxfInt( 70, 1);
dw.dxfInt( 71, 2);
dw.dxfReal( 10, 0.0);
dw.dxfReal( 20, 0.0);
dw.dxfReal( 11, 12.0);
dw.dxfReal( 21, 9.0);
dw.dxfReal( 12, 0.0);
dw.dxfReal( 22, 0.0);
dw.dxfReal( 32, 0.0);
dw.dxfReal( 14, 0.0);
dw.dxfReal( 24, 0.0);
dw.dxfReal( 34, 0.0);
dw.dxfReal( 15, 0.0);
dw.dxfReal( 25, 0.0);
dw.dxfReal( 35, 0.0);
dw.dxfReal(146, 0.0);
dw.dxfReal( 13, 0.0);
dw.dxfReal( 23, 0.0);
dw.dxfReal( 33, 0.0);
dw.dxfReal( 16, 1.0);
dw.dxfReal( 26, 0.0);
dw.dxfReal( 36, 0.0);
dw.dxfReal( 17, 0.0);
dw.dxfReal( 27, 1.0);
dw.dxfReal( 37, 0.0);
dw.dxfInt( 76, 0);
//dw.dxfHex(330, dw.getPaperSpace0Handle()); // 23
dw.dxfHex(330, 0x23);
dw.dxfString( 0, "DICTIONARY");
//dw.dxfHex(5, 0x2C);
//dicId5 =
dw.dxfHex(5, acDbVariableDictionaryHandle);
//dw.handle(); // 2C
//dw.dxfHex(330, 0xC); // C
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(281, 1);
dw.dxfString( 3, "DIMASSOC");
//dw.dxfHex(350, 0x2F);
dw.dxfHex(350, dw.getNextHandle()+1); // 2E
dw.dxfString( 3, "HIDETEXT");
//dw.dxfHex(350, 0x2E);
dw.dxfHex(350, dw.getNextHandle()); // 2D
dw.dxfString( 0, "DICTIONARYVAR");
//dw.dxfHex(5, 0x2E);
dw.handle(); // 2E
//dw.dxfHex(330, dicId5); // 2C
dw.dxfString(100, "DictionaryVariables");
dw.dxfInt(280, 0);
dw.dxfInt( 1, 2);
dw.dxfString( 0, "DICTIONARYVAR");
//dw.dxfHex(5, 0x2D);
dw.handle(); // 2D
//dw.dxfHex(330, dicId5); // 2C
dw.dxfString(100, "DictionaryVariables");
dw.dxfInt(280, 0);
dw.dxfInt( 1, 1);
}
void DL_Dxf::writeAppDictionary(DL_WriterA& dw) {
dw.dxfString( 0, "DICTIONARY");
//dw.handle();
dw.dxfHex(5, appDictionaryHandle);
dw.dxfString(100, "AcDbDictionary");
dw.dxfInt(281, 1);
}
int DL_Dxf::writeDictionaryEntry(DL_WriterA& dw, const std::string& name) {
dw.dxfString( 3, name);
int handle = 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, appDictionaryHandle);
dw.dxfString(100, "AcDbXrecord");
dw.dxfInt(280, 1);
dw.dxfInt(90, value);
}
void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, double value) {
dw.dxfString( 0, "XRECORD");
dw.dxfHex(5, handle);
dw.dxfHex(330, appDictionaryHandle);
dw.dxfString(100, "AcDbXrecord");
dw.dxfInt(280, 1);
dw.dxfReal(40, value);
}
void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, bool value) {
dw.dxfString( 0, "XRECORD");
dw.dxfHex(5, handle);
dw.dxfHex(330, appDictionaryHandle);
dw.dxfString(100, "AcDbXrecord");
dw.dxfInt(280, 1);
dw.dxfBool(290, value);
}
void DL_Dxf::writeXRecord(DL_WriterA& dw, int handle, const std::string& value) {
dw.dxfString( 0, "XRECORD");
dw.dxfHex(5, handle);
dw.dxfHex(330, appDictionaryHandle);
dw.dxfString(100, "AcDbXrecord");
dw.dxfInt(280, 1);
dw.dxfString(1000, value);
}
/**
* Writes the end of the objects section. This section is needed in DL_VERSION_R13.
* Note that this method currently only writes a faked OBJECTS section
* to make the file readable by Aut*cad.
*/
void DL_Dxf::writeObjectsEnd(DL_WriterA& dw) {
dw.dxfString( 0, "ENDSEC");
}
/**
* Writes a comment to the DXF file.
*/
void DL_Dxf::writeComment(DL_WriterA& dw, const std::string& comment) {
dw.dxfString(999, comment);
}
/**
* Checks if the given variable is known by the given DXF version.
*/
bool DL_Dxf::checkVariable(const char* var, DL_Codes::version version) {
if (version>=DL_VERSION_2000) {
return true;
} else if (version==DL_VERSION_R12) {
// these are all the variables recognized by dxf r12:
if (!strcmp(var, "$ACADVER")) {
return true;
}
if (!strcmp(var, "$ACADVER")) {
return true;
}
if (!strcmp(var, "$ANGBASE")) {
return true;
}
if (!strcmp(var, "$ANGDIR")) {
return true;
}
if (!strcmp(var, "$ATTDIA")) {
return true;
}
if (!strcmp(var, "$ATTMODE")) {
return true;
}
if (!strcmp(var, "$ATTREQ")) {
return true;
}
if (!strcmp(var, "$AUNITS")) {
return true;
}
if (!strcmp(var, "$AUPREC")) {
return true;
}
if (!strcmp(var, "$AXISMODE")) {
return true;
}
if (!strcmp(var, "$AXISUNIT")) {
return true;
}
if (!strcmp(var, "$BLIPMODE")) {
return true;
}
if (!strcmp(var, "$CECOLOR")) {
return true;
}
if (!strcmp(var, "$CELTYPE")) {
return true;
}
if (!strcmp(var, "$CHAMFERA")) {
return true;
}
if (!strcmp(var, "$CHAMFERB")) {
return true;
}
if (!strcmp(var, "$CLAYER")) {
return true;
}
if (!strcmp(var, "$COORDS")) {
return true;
}
if (!strcmp(var, "$DIMALT")) {
return true;
}
if (!strcmp(var, "$DIMALTD")) {
return true;
}
if (!strcmp(var, "$DIMALTF")) {
return true;
}
if (!strcmp(var, "$DIMAPOST")) {
return true;
}
if (!strcmp(var, "$DIMASO")) {
return true;
}
if (!strcmp(var, "$DIMASZ")) {
return true;
}
if (!strcmp(var, "$DIMBLK")) {
return true;
}
if (!strcmp(var, "$DIMBLK1")) {
return true;
}
if (!strcmp(var, "$DIMBLK2")) {
return true;
}
if (!strcmp(var, "$DIMCEN")) {
return true;
}
if (!strcmp(var, "$DIMCLRD")) {
return true;
}
if (!strcmp(var, "$DIMCLRE")) {
return true;
}
if (!strcmp(var, "$DIMCLRT")) {
return true;
}
if (!strcmp(var, "$DIMDLE")) {
return true;
}
if (!strcmp(var, "$DIMDLI")) {
return true;
}
if (!strcmp(var, "$DIMEXE")) {
return true;
}
if (!strcmp(var, "$DIMEXO")) {
return true;
}
if (!strcmp(var, "$DIMGAP")) {
return true;
}
if (!strcmp(var, "$DIMLFAC")) {
return true;
}
if (!strcmp(var, "$DIMLIM")) {
return true;
}
if (!strcmp(var, "$DIMPOST")) {
return true;
}
if (!strcmp(var, "$DIMRND")) {
return true;
}
if (!strcmp(var, "$DIMSAH")) {
return true;
}
if (!strcmp(var, "$DIMSCALE")) {
return true;
}
if (!strcmp(var, "$DIMSE1")) {
return true;
}
if (!strcmp(var, "$DIMSE2")) {
return true;
}
if (!strcmp(var, "$DIMSHO")) {
return true;
}
if (!strcmp(var, "$DIMSOXD")) {
return true;
}
if (!strcmp(var, "$DIMSTYLE")) {
return true;
}
if (!strcmp(var, "$DIMTAD")) {
return true;
}
if (!strcmp(var, "$DIMTFAC")) {
return true;
}
if (!strcmp(var, "$DIMTIH")) {
return true;
}
if (!strcmp(var, "$DIMTIX")) {
return true;
}
if (!strcmp(var, "$DIMTM")) {
return true;
}
if (!strcmp(var, "$DIMTOFL")) {
return true;
}
if (!strcmp(var, "$DIMTOH")) {
return true;
}
if (!strcmp(var, "$DIMTOL")) {
return true;
}
if (!strcmp(var, "$DIMTP")) {
return true;
}
if (!strcmp(var, "$DIMTSZ")) {
return true;
}
if (!strcmp(var, "$DIMTVP")) {
return true;
}
if (!strcmp(var, "$DIMTXT")) {
return true;
}
if (!strcmp(var, "$DIMZIN")) {
return true;
}
if (!strcmp(var, "$DWGCODEPAGE")) {
return true;
}
if (!strcmp(var, "$DRAGMODE")) {
return true;
}
if (!strcmp(var, "$ELEVATION")) {
return true;
}
if (!strcmp(var, "$EXTMAX")) {
return true;
}
if (!strcmp(var, "$EXTMIN")) {
return true;
}
if (!strcmp(var, "$FILLETRAD")) {
return true;
}
if (!strcmp(var, "$FILLMODE")) {
return true;
}
if (!strcmp(var, "$HANDLING")) {
return true;
}
if (!strcmp(var, "$HANDSEED")) {
return true;
}
if (!strcmp(var, "$INSBASE")) {
return true;
}
if (!strcmp(var, "$LIMCHECK")) {
return true;
}
if (!strcmp(var, "$LIMMAX")) {
return true;
}
if (!strcmp(var, "$LIMMIN")) {
return true;
}
if (!strcmp(var, "$LTSCALE")) {
return true;
}
if (!strcmp(var, "$LUNITS")) {
return true;
}
if (!strcmp(var, "$LUPREC")) {
return true;
}
if (!strcmp(var, "$MAXACTVP")) {
return true;
}
if (!strcmp(var, "$MENU")) {
return true;
}
if (!strcmp(var, "$MIRRTEXT")) {
return true;
}
if (!strcmp(var, "$ORTHOMODE")) {
return true;
}
if (!strcmp(var, "$OSMODE")) {
return true;
}
if (!strcmp(var, "$PDMODE")) {
return true;
}
if (!strcmp(var, "$PDSIZE")) {
return true;
}
if (!strcmp(var, "$PELEVATION")) {
return true;
}
if (!strcmp(var, "$PEXTMAX")) {
return true;
}
if (!strcmp(var, "$PEXTMIN")) {
return true;
}
if (!strcmp(var, "$PLIMCHECK")) {
return true;
}
if (!strcmp(var, "$PLIMMAX")) {
return true;
}
if (!strcmp(var, "$PLIMMIN")) {
return true;
}
if (!strcmp(var, "$PLINEGEN")) {
return true;
}
if (!strcmp(var, "$PLINEWID")) {
return true;
}
if (!strcmp(var, "$PSLTSCALE")) {
return true;
}
if (!strcmp(var, "$PUCSNAME")) {
return true;
}
if (!strcmp(var, "$PUCSORG")) {
return true;
}
if (!strcmp(var, "$PUCSXDIR")) {
return true;
}
if (!strcmp(var, "$PUCSYDIR")) {
return true;
}
if (!strcmp(var, "$QTEXTMODE")) {
return true;
}
if (!strcmp(var, "$REGENMODE")) {
return true;
}
if (!strcmp(var, "$SHADEDGE")) {
return true;
}
if (!strcmp(var, "$SHADEDIF")) {
return true;
}
if (!strcmp(var, "$SKETCHINC")) {
return true;
}
if (!strcmp(var, "$SKPOLY")) {
return true;
}
if (!strcmp(var, "$SPLFRAME")) {
return true;
}
if (!strcmp(var, "$SPLINESEGS")) {
return true;
}
if (!strcmp(var, "$SPLINETYPE")) {
return true;
}
if (!strcmp(var, "$SURFTAB1")) {
return true;
}
if (!strcmp(var, "$SURFTAB2")) {
return true;
}
if (!strcmp(var, "$SURFTYPE")) {
return true;
}
if (!strcmp(var, "$SURFU")) {
return true;
}
if (!strcmp(var, "$SURFV")) {
return true;
}
if (!strcmp(var, "$TDCREATE")) {
return true;
}
if (!strcmp(var, "$TDINDWG")) {
return true;
}
if (!strcmp(var, "$TDUPDATE")) {
return true;
}
if (!strcmp(var, "$TDUSRTIMER")) {
return true;
}
if (!strcmp(var, "$TEXTSIZE")) {
return true;
}
if (!strcmp(var, "$TEXTSTYLE")) {
return true;
}
if (!strcmp(var, "$THICKNESS")) {
return true;
}
if (!strcmp(var, "$TILEMODE")) {
return true;
}
if (!strcmp(var, "$TRACEWID")) {
return true;
}
if (!strcmp(var, "$UCSNAME")) {
return true;
}
if (!strcmp(var, "$UCSORG")) {
return true;
}
if (!strcmp(var, "$UCSXDIR")) {
return true;
}
if (!strcmp(var, "$UCSYDIR")) {
return true;
}
if (!strcmp(var, "$UNITMODE")) {
return true;
}
if (!strcmp(var, "$USERI1")) {
return true;
}
if (!strcmp(var, "$USERR1")) {
return true;
}
if (!strcmp(var, "$USRTIMER")) {
return true;
}
if (!strcmp(var, "$VISRETAIN")) {
return true;
}
if (!strcmp(var, "$WORLDVIEW")) {
return true;
}
if (!strcmp(var, "$FASTZOOM")) {
return true;
}
if (!strcmp(var, "$GRIDMODE")) {
return true;
}
if (!strcmp(var, "$GRIDUNIT")) {
return true;
}
if (!strcmp(var, "$SNAPANG")) {
return true;
}
if (!strcmp(var, "$SNAPBASE")) {
return true;
}
if (!strcmp(var, "$SNAPISOPAIR")) {
return true;
}
if (!strcmp(var, "$SNAPMODE")) {
return true;
}
if (!strcmp(var, "$SNAPSTYLE")) {
return true;
}
if (!strcmp(var, "$SNAPUNIT")) {
return true;
}
if (!strcmp(var, "$VIEWCTR")) {
return true;
}
if (!strcmp(var, "$VIEWDIR")) {
return true;
}
if (!strcmp(var, "$VIEWSIZE")) {
return true;
}
return false;
}
return false;
}
/**
* @returns the library version as int (4 bytes, each byte one version number).
* e.g. if str = "2.0.2.0" getLibVersion returns 0x02000200
*/
int DL_Dxf::getLibVersion(const std::string& str) {
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] = 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];
std::strcpy(buf1, " 10\n");
std::strcpy(buf2, "10");
std::strcpy(buf3, "10\n");
std::strcpy(buf4, " 10 \n");
std::strcpy(buf5, " 10 \r");
std::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";
}