| | |
| |
|
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <cmath> |
| | #include <fstream> |
| | #include <iomanip> |
| | #include <iostream> |
| | #include <sstream> |
| | #include <exception> |
| | #include <string> |
| |
|
| | #include "dxf.h" |
| | #include <App/Application.h> |
| | #include <Base/Color.h> |
| | #include <Base/Console.h> |
| | #include <Base/Exception.h> |
| | #include <Base/FileInfo.h> |
| | #include <Base/Interpreter.h> |
| | #include <Base/Stream.h> |
| | #include <Base/Tools.h> |
| | #include <Base/Vector3D.h> |
| |
|
| |
|
| | using namespace std; |
| |
|
| | namespace |
| | { |
| |
|
| | std::string DxfUnitToString(DxfUnits::eDxfUnits_t unit) |
| | { |
| | switch (unit) { |
| | case DxfUnits::eInches: |
| | return "Inches"; |
| | case DxfUnits::eFeet: |
| | return "Feet"; |
| | case DxfUnits::eMiles: |
| | return "Miles"; |
| | case DxfUnits::eMillimeters: |
| | return "Millimeters"; |
| | case DxfUnits::eCentimeters: |
| | return "Centimeters"; |
| | case DxfUnits::eMeters: |
| | return "Meters"; |
| | case DxfUnits::eKilometers: |
| | return "Kilometers"; |
| | case DxfUnits::eMicroinches: |
| | return "Microinches"; |
| | case DxfUnits::eMils: |
| | return "Mils"; |
| | case DxfUnits::eYards: |
| | return "Yards"; |
| | case DxfUnits::eAngstroms: |
| | return "Angstroms"; |
| | case DxfUnits::eNanometers: |
| | return "Nanometers"; |
| | case DxfUnits::eMicrons: |
| | return "Microns"; |
| | case DxfUnits::eDecimeters: |
| | return "Decimeters"; |
| | case DxfUnits::eDekameters: |
| | return "Dekameters"; |
| | case DxfUnits::eHectometers: |
| | return "Hectometers"; |
| | case DxfUnits::eGigameters: |
| | return "Gigameters"; |
| | case DxfUnits::eAstronomicalUnits: |
| | return "Astronomical Units"; |
| | case DxfUnits::eLightYears: |
| | return "Light Years"; |
| | case DxfUnits::eParsecs: |
| | return "Parsecs"; |
| | case DxfUnits::eUnspecified: |
| | default: |
| | return "Unspecified"; |
| | } |
| | } |
| |
|
| | } |
| |
|
| | static Base::Vector3d MakeVector3d(const double coordinates[3]) |
| | { |
| | |
| | |
| | return Base::Vector3d(coordinates[0], coordinates[1], coordinates[2]); |
| | } |
| |
|
| | CDxfWrite::CDxfWrite(const char* filepath) |
| | : |
| | |
| | |
| | |
| | |
| |
|
| | m_fail(false) |
| | , m_ssBlock(new std::ostringstream()) |
| | , m_ssBlkRecord(new std::ostringstream()) |
| | , m_ssEntity(new std::ostringstream()) |
| | , m_ssLayer(new std::ostringstream()) |
| | , m_version(12) |
| | , m_handle(0xA00) |
| | , |
| | |
| | |
| | |
| | |
| | m_polyOverride(false) |
| | , m_layerName("none") |
| | { |
| | |
| | Base::FileInfo fi(filepath); |
| | m_ofs = new Base::ofstream(fi, ios::out); |
| |
|
| | if (!(*m_ofs)) { |
| | m_fail = true; |
| | return; |
| | } |
| | m_ofs->imbue(std::locale("C")); |
| |
|
| | |
| | m_ssEntity->setf(std::ios::fixed); |
| | m_ssEntity->precision(9); |
| | } |
| |
|
| | CDxfWrite::~CDxfWrite() |
| | { |
| | delete m_ofs; |
| | delete m_ssBlock; |
| | delete m_ssBlkRecord; |
| | delete m_ssEntity; |
| | delete m_ssLayer; |
| | } |
| |
|
| | void CDxfWrite::init() |
| | { |
| | writeHeaderSection(); |
| | makeBlockRecordTableHead(); |
| | makeBlockSectionHead(); |
| | } |
| |
|
| | |
| | void CDxfWrite::endRun() |
| | { |
| | makeLayerTable(); |
| | makeBlockRecordTableBody(); |
| |
|
| | writeClassesSection(); |
| | writeTablesSection(); |
| | writeBlocksSection(); |
| | writeEntitiesSection(); |
| | writeObjectsSection(); |
| |
|
| | (*m_ofs) << " 0" << endl; |
| | (*m_ofs) << "EOF"; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeHeaderSection() |
| | { |
| | std::stringstream ss; |
| | ss << "FreeCAD v" << App::Application::Config()["BuildVersionMajor"] << "." |
| | << App::Application::Config()["BuildVersionMinor"] << " " |
| | << App::Application::Config()["BuildRevision"]; |
| |
|
| | |
| | (*m_ofs) << "999" << endl; |
| | (*m_ofs) << ss.str() << endl; |
| |
|
| | |
| | ss.str(""); |
| | ss.clear(); |
| | ss << "header" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeClassesSection() |
| | { |
| | if (m_version < 14) { |
| | return; |
| | } |
| |
|
| | |
| | std::stringstream ss; |
| | ss << "classes" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeTablesSection() |
| | { |
| | |
| | std::stringstream ss; |
| | ss << "tables1" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| |
|
| | (*m_ofs) << (*m_ssLayer).str(); |
| |
|
| | |
| | ss.str(""); |
| | ss.clear(); |
| | ss << "tables2" << m_version << ".rub"; |
| | fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| |
|
| | if (m_version > 12) { |
| | (*m_ofs) << (*m_ssBlkRecord).str(); |
| | (*m_ofs) << " 0" << endl; |
| | (*m_ofs) << "ENDTAB" << endl; |
| | } |
| | (*m_ofs) << " 0" << endl; |
| | (*m_ofs) << "ENDSEC" << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::makeLayerTable() |
| | { |
| | std::string tablehash = getLayerHandle(); |
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << "TABLE" << endl; |
| | (*m_ssLayer) << " 2" << endl; |
| | (*m_ssLayer) << "LAYER" << endl; |
| | (*m_ssLayer) << " 5" << endl; |
| | (*m_ssLayer) << tablehash << endl; |
| | if (m_version > 12) { |
| | (*m_ssLayer) << "330" << endl; |
| | (*m_ssLayer) << 0 << endl; |
| | (*m_ssLayer) << "100" << endl; |
| | (*m_ssLayer) << "AcDbSymbolTable" << endl; |
| | } |
| | (*m_ssLayer) << " 70" << endl; |
| | (*m_ssLayer) << m_layerList.size() + 1 << endl; |
| |
|
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << "LAYER" << endl; |
| | (*m_ssLayer) << " 5" << endl; |
| | (*m_ssLayer) << getLayerHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssLayer) << "330" << endl; |
| | (*m_ssLayer) << tablehash << endl; |
| | (*m_ssLayer) << "100" << endl; |
| | (*m_ssLayer) << "AcDbSymbolTableRecord" << endl; |
| | (*m_ssLayer) << "100" << endl; |
| | (*m_ssLayer) << "AcDbLayerTableRecord" << endl; |
| | } |
| | (*m_ssLayer) << " 2" << endl; |
| | (*m_ssLayer) << "0" << endl; |
| | (*m_ssLayer) << " 70" << endl; |
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << " 62" << endl; |
| | (*m_ssLayer) << " 7" << endl; |
| | (*m_ssLayer) << " 6" << endl; |
| | (*m_ssLayer) << "CONTINUOUS" << endl; |
| |
|
| | for (auto& l : m_layerList) { |
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << "LAYER" << endl; |
| | (*m_ssLayer) << " 5" << endl; |
| | (*m_ssLayer) << getLayerHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssLayer) << "330" << endl; |
| | (*m_ssLayer) << tablehash << endl; |
| | (*m_ssLayer) << "100" << endl; |
| | (*m_ssLayer) << "AcDbSymbolTableRecord" << endl; |
| | (*m_ssLayer) << "100" << endl; |
| | (*m_ssLayer) << "AcDbLayerTableRecord" << endl; |
| | } |
| | (*m_ssLayer) << " 2" << endl; |
| | (*m_ssLayer) << l << endl; |
| | (*m_ssLayer) << " 70" << endl; |
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << " 62" << endl; |
| | (*m_ssLayer) << " 7" << endl; |
| | (*m_ssLayer) << " 6" << endl; |
| | (*m_ssLayer) << "CONTINUOUS" << endl; |
| | } |
| | (*m_ssLayer) << " 0" << endl; |
| | (*m_ssLayer) << "ENDTAB" << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::makeBlockRecordTableHead() |
| | { |
| | if (m_version < 14) { |
| | return; |
| | } |
| | std::string tablehash = getBlkRecordHandle(); |
| | m_saveBlockRecordTableHandle = tablehash; |
| | (*m_ssBlkRecord) << " 0" << endl; |
| | (*m_ssBlkRecord) << "TABLE" << endl; |
| | (*m_ssBlkRecord) << " 2" << endl; |
| | (*m_ssBlkRecord) << "BLOCK_RECORD" << endl; |
| | (*m_ssBlkRecord) << " 5" << endl; |
| | (*m_ssBlkRecord) << tablehash << endl; |
| | (*m_ssBlkRecord) << "330" << endl; |
| | (*m_ssBlkRecord) << "0" << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbSymbolTable" << endl; |
| | (*m_ssBlkRecord) << " 70" << endl; |
| | (*m_ssBlkRecord) << (m_blockList.size() + 5) << endl; |
| |
|
| | m_saveModelSpaceHandle = getBlkRecordHandle(); |
| | (*m_ssBlkRecord) << " 0" << endl; |
| | (*m_ssBlkRecord) << "BLOCK_RECORD" << endl; |
| | (*m_ssBlkRecord) << " 5" << endl; |
| | (*m_ssBlkRecord) << m_saveModelSpaceHandle << endl; |
| | (*m_ssBlkRecord) << "330" << endl; |
| | (*m_ssBlkRecord) << tablehash << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbSymbolTableRecord" << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbBlockTableRecord" << endl; |
| | (*m_ssBlkRecord) << " 2" << endl; |
| | (*m_ssBlkRecord) << "*MODEL_SPACE" << endl; |
| | |
| | |
| |
|
| | m_savePaperSpaceHandle = getBlkRecordHandle(); |
| | (*m_ssBlkRecord) << " 0" << endl; |
| | (*m_ssBlkRecord) << "BLOCK_RECORD" << endl; |
| | (*m_ssBlkRecord) << " 5" << endl; |
| | (*m_ssBlkRecord) << m_savePaperSpaceHandle << endl; |
| | (*m_ssBlkRecord) << "330" << endl; |
| | (*m_ssBlkRecord) << tablehash << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbSymbolTableRecord" << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbBlockTableRecord" << endl; |
| | (*m_ssBlkRecord) << " 2" << endl; |
| | (*m_ssBlkRecord) << "*PAPER_SPACE" << endl; |
| | |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::makeBlockRecordTableBody() |
| | { |
| | if (m_version < 14) { |
| | return; |
| | } |
| |
|
| | int iBlkRecord = 0; |
| | for (auto& b : m_blockList) { |
| | (*m_ssBlkRecord) << " 0" << endl; |
| | (*m_ssBlkRecord) << "BLOCK_RECORD" << endl; |
| | (*m_ssBlkRecord) << " 5" << endl; |
| | (*m_ssBlkRecord) << m_blkRecordList.at(iBlkRecord) << endl; |
| | (*m_ssBlkRecord) << "330" << endl; |
| | (*m_ssBlkRecord) << m_saveBlockRecordTableHandle << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbSymbolTableRecord" << endl; |
| | (*m_ssBlkRecord) << "100" << endl; |
| | (*m_ssBlkRecord) << "AcDbBlockTableRecord" << endl; |
| | (*m_ssBlkRecord) << " 2" << endl; |
| | (*m_ssBlkRecord) << b << endl; |
| | |
| | |
| | iBlkRecord++; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::makeBlockSectionHead() |
| | { |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "SECTION" << endl; |
| | (*m_ssBlock) << " 2" << endl; |
| | (*m_ssBlock) << "BLOCKS" << endl; |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "BLOCK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | m_currentBlock = getBlockHandle(); |
| | (*m_ssBlock) << m_currentBlock << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_saveModelSpaceHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << "0" << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockBegin" << endl; |
| | } |
| | (*m_ssBlock) << " 2" << endl; |
| | (*m_ssBlock) << "*MODEL_SPACE" << endl; |
| | (*m_ssBlock) << " 70" << endl; |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << " 10" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 20" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 30" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 3" << endl; |
| | (*m_ssBlock) << "*MODEL_SPACE" << endl; |
| | (*m_ssBlock) << " 1" << endl; |
| | (*m_ssBlock) << " " << endl; |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "ENDBLK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | (*m_ssBlock) << getBlockHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_saveModelSpaceHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << "0" << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockEnd" << endl; |
| | } |
| |
|
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "BLOCK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | m_currentBlock = getBlockHandle(); |
| | (*m_ssBlock) << m_currentBlock << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_savePaperSpaceHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | (*m_ssBlock) << " 67" << endl; |
| | (*m_ssBlock) << "1" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << "0" << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockBegin" << endl; |
| | } |
| | (*m_ssBlock) << " 2" << endl; |
| | (*m_ssBlock) << "*PAPER_SPACE" << endl; |
| | (*m_ssBlock) << " 70" << endl; |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << " 10" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 20" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 30" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 3" << endl; |
| | (*m_ssBlock) << "*PAPER_SPACE" << endl; |
| | (*m_ssBlock) << " 1" << endl; |
| | (*m_ssBlock) << " " << endl; |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "ENDBLK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | (*m_ssBlock) << getBlockHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_savePaperSpaceHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | (*m_ssBlock) << " 67" << endl; |
| | (*m_ssBlock) << " 1" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << "0" << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockEnd" << endl; |
| | } |
| | } |
| |
|
| | std::string CDxfWrite::getPlateFile(std::string fileSpec) |
| | { |
| | std::stringstream outString; |
| | Base::FileInfo fi(fileSpec); |
| | if (!fi.isReadable()) { |
| | Base::Console().message("dxf unable to open %s!\n", fileSpec.c_str()); |
| | } |
| | else { |
| | string line; |
| | ifstream inFile(fi.filePath()); |
| |
|
| | while (!inFile.eof()) { |
| | getline(inFile, line); |
| | if (!inFile.eof()) { |
| | outString << line << '\n'; |
| | } |
| | } |
| | } |
| | return outString.str(); |
| | } |
| |
|
| | std::string CDxfWrite::getHandle() |
| | { |
| | m_handle++; |
| | std::stringstream ss; |
| | ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2); |
| | ss << m_handle; |
| | return ss.str(); |
| | } |
| |
|
| | std::string CDxfWrite::getEntityHandle() |
| | { |
| | return getHandle(); |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | std::string CDxfWrite::getLayerHandle() |
| | { |
| | return getHandle(); |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | std::string CDxfWrite::getBlockHandle() |
| | { |
| | return getHandle(); |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | std::string CDxfWrite::getBlkRecordHandle() |
| | { |
| | return getHandle(); |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | void CDxfWrite::addBlockName(const std::string& name, const std::string& blkRecordHandle) |
| | { |
| | m_blockList.push_back(name); |
| | m_blkRecordList.push_back(blkRecordHandle); |
| | } |
| |
|
| | void CDxfWrite::setLayerName(std::string name) |
| | { |
| | m_layerName = name; |
| | m_layerList.push_back(name); |
| | } |
| |
|
| | void CDxfWrite::writeLine(const double* start, const double* end) |
| | { |
| | putLine(toVector3d(start), toVector3d(end), m_ssEntity, getEntityHandle(), m_saveModelSpaceHandle); |
| | } |
| |
|
| | void CDxfWrite::putLine( |
| | const Base::Vector3d& start, |
| | const Base::Vector3d& end, |
| | std::ostringstream* outStream, |
| | const std::string& handle, |
| | const std::string& ownerHandle |
| | ) |
| | { |
| | (*outStream) << " 0" << endl; |
| | (*outStream) << "LINE" << endl; |
| | (*outStream) << " 5" << endl; |
| | (*outStream) << handle << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "330" << endl; |
| | (*outStream) << ownerHandle << endl; |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbEntity" << endl; |
| | } |
| | (*outStream) << " 8" << endl; |
| | (*outStream) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbLine" << endl; |
| | } |
| | (*outStream) << " 10" << endl; |
| | (*outStream) << start.x << endl; |
| | (*outStream) << " 20" << endl; |
| | (*outStream) << start.y << endl; |
| | (*outStream) << " 30" << endl; |
| | (*outStream) << start.z << endl; |
| | (*outStream) << " 11" << endl; |
| | (*outStream) << end.x << endl; |
| | (*outStream) << " 21" << endl; |
| | (*outStream) << end.y << endl; |
| | (*outStream) << " 31" << endl; |
| | (*outStream) << end.z << endl; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeLWPolyLine(const LWPolyDataOut& pd) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "LWPOLYLINE" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbPolyline" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | (*m_ssEntity) << " 90" << endl; |
| | (*m_ssEntity) << pd.nVert << endl; |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << pd.Flag << endl; |
| | (*m_ssEntity) << " 43" << endl; |
| | (*m_ssEntity) << "0" << endl; |
| | |
| | |
| | |
| | |
| | |
| | for (auto& p : pd.Verts) { |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << p.x << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << p.y << endl; |
| | } |
| | for (auto& s : pd.StartWidth) { |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << s << endl; |
| | } |
| | for (auto& e : pd.EndWidth) { |
| | (*m_ssEntity) << " 41" << endl; |
| | (*m_ssEntity) << e << endl; |
| | } |
| | for (auto& b : pd.Bulge) { |
| | (*m_ssEntity) << " 42" << endl; |
| | (*m_ssEntity) << b << endl; |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writePolyline(const LWPolyDataOut& pd) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "POLYLINE" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbPolyline" << endl; |
| | } |
| | (*m_ssEntity) << " 66" << endl; |
| | (*m_ssEntity) << " 1" << endl; |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << "0.0" << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << "0.0" << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << "0.0" << endl; |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << "0" << endl; |
| | for (auto& p : pd.Verts) { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "VERTEX" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << p.x << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << p.y << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << p.z << endl; |
| | } |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "SEQEND" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | } |
| |
|
| | void CDxfWrite::writePoint(const double* point) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "POINT" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbPoint" << endl; |
| | } |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << point[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << point[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << point[2] << endl; |
| | } |
| |
|
| | |
| | |
| | void CDxfWrite::writeArc(const double* start, const double* end, const double* center, bool dir) |
| | |
| | { |
| | double ax = start[0] - center[0]; |
| | double ay = start[1] - center[1]; |
| | double bx = end[0] - center[0]; |
| | double by = end[1] - center[1]; |
| |
|
| | double start_angle = Base::toDegrees(atan2(ay, ax)); |
| | double end_angle = Base::toDegrees(atan2(by, bx)); |
| | double radius = sqrt(ax * ax + ay * ay); |
| | if (!dir) { |
| | double temp = start_angle; |
| | start_angle = end_angle; |
| | end_angle = temp; |
| | } |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "ARC" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | |
| | |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbCircle" << endl; |
| | } |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << center[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << center[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << center[2] << endl; |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << radius << endl; |
| |
|
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbArc" << endl; |
| | } |
| | (*m_ssEntity) << " 50" << endl; |
| | (*m_ssEntity) << start_angle << endl; |
| | (*m_ssEntity) << " 51" << endl; |
| | (*m_ssEntity) << end_angle << endl; |
| | } |
| |
|
| | void CDxfWrite::writeCircle(const double* center, double radius) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "CIRCLE" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbCircle" << endl; |
| | } |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << center[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << center[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << center[2] << endl; |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << radius << endl; |
| | } |
| |
|
| | void CDxfWrite::writeEllipse( |
| | const double* center, |
| | double major_radius, |
| | double minor_radius, |
| | double rotation, |
| | double start_angle, |
| | double end_angle, |
| | bool endIsCW |
| | ) |
| | { |
| | Base::Vector3d m(major_radius * sin(rotation), major_radius * cos(rotation), 0); |
| | double ratio = minor_radius / major_radius; |
| |
|
| | if (!endIsCW) { |
| | double temp = start_angle; |
| | start_angle = end_angle; |
| | end_angle = temp; |
| | } |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "ELLIPSE" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEllipse" << endl; |
| | } |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << center[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << center[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << center[2] << endl; |
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << m.x << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << m.y << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << m.z << endl; |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << ratio << endl; |
| | |
| | |
| | |
| | |
| | |
| | |
| | (*m_ssEntity) << " 41" << endl; |
| | (*m_ssEntity) << start_angle << endl; |
| | (*m_ssEntity) << " 42" << endl; |
| | (*m_ssEntity) << end_angle << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeSpline(const SplineDataOut& sd) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "SPLINE" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbSpline" << endl; |
| | } |
| | (*m_ssEntity) << "210" << endl; |
| | (*m_ssEntity) << "0" << endl; |
| | (*m_ssEntity) << "220" << endl; |
| | (*m_ssEntity) << "0" << endl; |
| | (*m_ssEntity) << "230" << endl; |
| | (*m_ssEntity) << "1" << endl; |
| |
|
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << sd.flag << endl; |
| | (*m_ssEntity) << " 71" << endl; |
| | (*m_ssEntity) << sd.degree << endl; |
| | (*m_ssEntity) << " 72" << endl; |
| | (*m_ssEntity) << sd.knots << endl; |
| | (*m_ssEntity) << " 73" << endl; |
| | (*m_ssEntity) << sd.control_points << endl; |
| | (*m_ssEntity) << " 74" << endl; |
| | (*m_ssEntity) << 0 << endl; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | for (auto& k : sd.knot) { |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << k << endl; |
| | } |
| |
|
| | for (auto& w : sd.weight) { |
| | (*m_ssEntity) << " 41" << endl; |
| | (*m_ssEntity) << w << endl; |
| | } |
| |
|
| | for (auto& center : sd.control) { |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << center.x << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << center.y << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << center.z << endl; |
| | } |
| | for (auto& f : sd.fit) { |
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << f.x << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << f.y << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << f.z << endl; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeVertex(double x, double y, double z) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "VERTEX" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbVertex" << endl; |
| | } |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << x << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << y << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << z << endl; |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 0 << endl; |
| | } |
| |
|
| | void CDxfWrite::writeText( |
| | const char* text, |
| | const double* location1, |
| | const double* location2, |
| | const double height, |
| | const int horizJust |
| | ) |
| | { |
| | putText( |
| | text, |
| | toVector3d(location1), |
| | toVector3d(location2), |
| | height, |
| | horizJust, |
| | m_ssEntity, |
| | getEntityHandle(), |
| | m_saveModelSpaceHandle |
| | ); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::putText( |
| | const char* text, |
| | const Base::Vector3d& location1, |
| | const Base::Vector3d& location2, |
| | const double height, |
| | const int horizJust, |
| | std::ostringstream* outStream, |
| | const std::string& handle, |
| | const std::string& ownerHandle |
| | ) |
| | { |
| | (void)location2; |
| |
|
| | (*outStream) << " 0" << endl; |
| | (*outStream) << "TEXT" << endl; |
| | (*outStream) << " 5" << endl; |
| | (*outStream) << handle << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "330" << endl; |
| | (*outStream) << ownerHandle << endl; |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbEntity" << endl; |
| | } |
| | (*outStream) << " 8" << endl; |
| | (*outStream) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbText" << endl; |
| | } |
| | |
| | |
| | (*outStream) << " 10" << endl; |
| | (*outStream) << location1.x << endl; |
| | (*outStream) << " 20" << endl; |
| | (*outStream) << location1.y << endl; |
| | (*outStream) << " 30" << endl; |
| | (*outStream) << location1.z << endl; |
| | (*outStream) << " 40" << endl; |
| | (*outStream) << height << endl; |
| | (*outStream) << " 1" << endl; |
| | (*outStream) << text << endl; |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | (*outStream) << " 7" << endl; |
| | (*outStream) << "STANDARD" << endl; |
| | |
| | |
| | (*outStream) << " 72" << endl; |
| | (*outStream) << horizJust << endl; |
| | |
| | |
| | (*outStream) << " 11" << endl; |
| | (*outStream) << location2.x << endl; |
| | (*outStream) << " 21" << endl; |
| | (*outStream) << location2.y << endl; |
| | (*outStream) << " 31" << endl; |
| | (*outStream) << location2.z << endl; |
| | |
| | |
| | |
| | |
| | |
| | |
| | if (m_version > 12) { |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbText" << endl; |
| | } |
| | } |
| |
|
| | void CDxfWrite::putArrow( |
| | Base::Vector3d& arrowPos, |
| | Base::Vector3d& barb1Pos, |
| | Base::Vector3d& barb2Pos, |
| | std::ostringstream* outStream, |
| | const std::string& handle, |
| | const std::string& ownerHandle |
| | ) |
| | { |
| | (*outStream) << " 0" << endl; |
| | (*outStream) << "SOLID" << endl; |
| | (*outStream) << " 5" << endl; |
| | (*outStream) << handle << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "330" << endl; |
| | (*outStream) << ownerHandle << endl; |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbEntity" << endl; |
| | } |
| | (*outStream) << " 8" << endl; |
| | (*outStream) << "0" << endl; |
| | (*outStream) << " 62" << endl; |
| | (*outStream) << " 0" << endl; |
| | if (m_version > 12) { |
| | (*outStream) << "100" << endl; |
| | (*outStream) << "AcDbTrace" << endl; |
| | } |
| | (*outStream) << " 10" << endl; |
| | (*outStream) << barb1Pos.x << endl; |
| | (*outStream) << " 20" << endl; |
| | (*outStream) << barb1Pos.y << endl; |
| | (*outStream) << " 30" << endl; |
| | (*outStream) << barb1Pos.z << endl; |
| | (*outStream) << " 11" << endl; |
| | (*outStream) << barb2Pos.x << endl; |
| | (*outStream) << " 21" << endl; |
| | (*outStream) << barb2Pos.y << endl; |
| | (*outStream) << " 31" << endl; |
| | (*outStream) << barb2Pos.z << endl; |
| | (*outStream) << " 12" << endl; |
| | (*outStream) << arrowPos.x << endl; |
| | (*outStream) << " 22" << endl; |
| | (*outStream) << arrowPos.y << endl; |
| | (*outStream) << " 32" << endl; |
| | (*outStream) << arrowPos.z << endl; |
| | (*outStream) << " 13" << endl; |
| | (*outStream) << arrowPos.x << endl; |
| | (*outStream) << " 23" << endl; |
| | (*outStream) << arrowPos.y << endl; |
| | (*outStream) << " 33" << endl; |
| | (*outStream) << arrowPos.z << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | #define ALIGNED 0 |
| | #define HORIZONTAL 1 |
| | #define VERTICAL 2 |
| | void CDxfWrite::writeLinearDim( |
| | const double* textMidPoint, |
| | const double* lineDefPoint, |
| | const double* extLine1, |
| | const double* extLine2, |
| | const char* dimText, |
| | int type |
| | ) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "DIMENSION" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 2" << endl; |
| | (*m_ssEntity) << "*" << getLayerName() << endl; |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << lineDefPoint[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << lineDefPoint[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << lineDefPoint[2] << endl; |
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << textMidPoint[0] << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << textMidPoint[1] << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << textMidPoint[2] << endl; |
| | if (type == ALIGNED) { |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 1 << endl; |
| | } |
| | if ((type == HORIZONTAL) || (type == VERTICAL)) { |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 32 << endl; |
| | } |
| | |
| | |
| | (*m_ssEntity) << " 1" << endl; |
| | (*m_ssEntity) << dimText << endl; |
| | (*m_ssEntity) << " 3" << endl; |
| | (*m_ssEntity) << "STANDARD" << endl; |
| | |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbAlignedDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 13" << endl; |
| | (*m_ssEntity) << extLine1[0] << endl; |
| | (*m_ssEntity) << " 23" << endl; |
| | (*m_ssEntity) << extLine1[1] << endl; |
| | (*m_ssEntity) << " 33" << endl; |
| | (*m_ssEntity) << extLine1[2] << endl; |
| | (*m_ssEntity) << " 14" << endl; |
| | (*m_ssEntity) << extLine2[0] << endl; |
| | (*m_ssEntity) << " 24" << endl; |
| | (*m_ssEntity) << extLine2[1] << endl; |
| | (*m_ssEntity) << " 34" << endl; |
| | (*m_ssEntity) << extLine2[2] << endl; |
| | if (m_version > 12) { |
| | if (type == VERTICAL) { |
| | (*m_ssEntity) << " 50" << endl; |
| | (*m_ssEntity) << "90" << endl; |
| | } |
| | if ((type == HORIZONTAL) || (type == VERTICAL)) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbRotatedDimension" << endl; |
| | } |
| | } |
| |
|
| | writeDimBlockPreamble(); |
| | writeLinearDimBlock(textMidPoint, lineDefPoint, extLine1, extLine2, dimText, type); |
| | writeBlockTrailer(); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeAngularDim( |
| | const double* textMidPoint, |
| | const double* lineDefPoint, |
| | const double* startExt1, |
| | const double* endExt1, |
| | const double* startExt2, |
| | const double* endExt2, |
| | const char* dimText |
| | ) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "DIMENSION" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 2" << endl; |
| | (*m_ssEntity) << "*" << getLayerName() << endl; |
| |
|
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << endExt2[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << endExt2[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << endExt2[2] << endl; |
| |
|
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << textMidPoint[0] << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << textMidPoint[1] << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << textMidPoint[2] << endl; |
| |
|
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 2 << endl; |
| | |
| | |
| | |
| | (*m_ssEntity) << " 1" << endl; |
| | (*m_ssEntity) << dimText << endl; |
| | (*m_ssEntity) << " 3" << endl; |
| | (*m_ssEntity) << "STANDARD" << endl; |
| | |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDb2LineAngularDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 13" << endl; |
| | (*m_ssEntity) << startExt1[0] << endl; |
| | (*m_ssEntity) << " 23" << endl; |
| | (*m_ssEntity) << startExt1[1] << endl; |
| | (*m_ssEntity) << " 33" << endl; |
| | (*m_ssEntity) << startExt1[2] << endl; |
| |
|
| | (*m_ssEntity) << " 14" << endl; |
| | (*m_ssEntity) << endExt1[0] << endl; |
| | (*m_ssEntity) << " 24" << endl; |
| | (*m_ssEntity) << endExt1[1] << endl; |
| | (*m_ssEntity) << " 34" << endl; |
| | (*m_ssEntity) << endExt1[2] << endl; |
| |
|
| | (*m_ssEntity) << " 15" << endl; |
| | (*m_ssEntity) << startExt2[0] << endl; |
| | (*m_ssEntity) << " 25" << endl; |
| | (*m_ssEntity) << startExt2[1] << endl; |
| | (*m_ssEntity) << " 35" << endl; |
| | (*m_ssEntity) << startExt2[2] << endl; |
| |
|
| | (*m_ssEntity) << " 16" << endl; |
| | (*m_ssEntity) << lineDefPoint[0] << endl; |
| | (*m_ssEntity) << " 26" << endl; |
| | (*m_ssEntity) << lineDefPoint[1] << endl; |
| | (*m_ssEntity) << " 36" << endl; |
| | (*m_ssEntity) << lineDefPoint[2] << endl; |
| | writeDimBlockPreamble(); |
| | writeAngularDimBlock(textMidPoint, lineDefPoint, startExt1, endExt1, startExt2, endExt2, dimText); |
| | writeBlockTrailer(); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeRadialDim( |
| | const double* centerPoint, |
| | const double* textMidPoint, |
| | const double* arcPoint, |
| | const char* dimText |
| | ) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "DIMENSION" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 2" << endl; |
| | (*m_ssEntity) << "*" << getLayerName() << endl; |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << centerPoint[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << centerPoint[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << centerPoint[2] << endl; |
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << textMidPoint[0] << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << textMidPoint[1] << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << textMidPoint[2] << endl; |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 4 << endl; |
| | |
| | |
| | (*m_ssEntity) << " 1" << endl; |
| | (*m_ssEntity) << dimText << endl; |
| | (*m_ssEntity) << " 3" << endl; |
| | (*m_ssEntity) << "STANDARD" << endl; |
| | |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbRadialDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 15" << endl; |
| | (*m_ssEntity) << arcPoint[0] << endl; |
| | (*m_ssEntity) << " 25" << endl; |
| | (*m_ssEntity) << arcPoint[1] << endl; |
| | (*m_ssEntity) << " 35" << endl; |
| | (*m_ssEntity) << arcPoint[2] << endl; |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << 0 << endl; |
| |
|
| | writeDimBlockPreamble(); |
| | writeRadialDimBlock(centerPoint, textMidPoint, arcPoint, dimText); |
| | writeBlockTrailer(); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeDiametricDim( |
| | const double* textMidPoint, |
| | const double* arcPoint1, |
| | const double* arcPoint2, |
| | const char* dimText |
| | ) |
| | { |
| | (*m_ssEntity) << " 0" << endl; |
| | (*m_ssEntity) << "DIMENSION" << endl; |
| | (*m_ssEntity) << " 5" << endl; |
| | (*m_ssEntity) << getEntityHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "330" << endl; |
| | (*m_ssEntity) << m_saveModelSpaceHandle << endl; |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssEntity) << " 8" << endl; |
| | (*m_ssEntity) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 2" << endl; |
| | (*m_ssEntity) << "*" << getLayerName() << endl; |
| | (*m_ssEntity) << " 10" << endl; |
| | (*m_ssEntity) << arcPoint1[0] << endl; |
| | (*m_ssEntity) << " 20" << endl; |
| | (*m_ssEntity) << arcPoint1[1] << endl; |
| | (*m_ssEntity) << " 30" << endl; |
| | (*m_ssEntity) << arcPoint1[2] << endl; |
| | (*m_ssEntity) << " 11" << endl; |
| | (*m_ssEntity) << textMidPoint[0] << endl; |
| | (*m_ssEntity) << " 21" << endl; |
| | (*m_ssEntity) << textMidPoint[1] << endl; |
| | (*m_ssEntity) << " 31" << endl; |
| | (*m_ssEntity) << textMidPoint[2] << endl; |
| | (*m_ssEntity) << " 70" << endl; |
| | (*m_ssEntity) << 3 << endl; |
| | |
| | |
| | (*m_ssEntity) << " 1" << endl; |
| | (*m_ssEntity) << dimText << endl; |
| | (*m_ssEntity) << " 3" << endl; |
| | (*m_ssEntity) << "STANDARD" << endl; |
| | |
| | if (m_version > 12) { |
| | (*m_ssEntity) << "100" << endl; |
| | (*m_ssEntity) << "AcDbDiametricDimension" << endl; |
| | } |
| | (*m_ssEntity) << " 15" << endl; |
| | (*m_ssEntity) << arcPoint2[0] << endl; |
| | (*m_ssEntity) << " 25" << endl; |
| | (*m_ssEntity) << arcPoint2[1] << endl; |
| | (*m_ssEntity) << " 35" << endl; |
| | (*m_ssEntity) << arcPoint2[2] << endl; |
| | (*m_ssEntity) << " 40" << endl; |
| | (*m_ssEntity) << 0 << endl; |
| |
|
| | writeDimBlockPreamble(); |
| | writeDiametricDimBlock(textMidPoint, arcPoint1, arcPoint2, dimText); |
| | writeBlockTrailer(); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeDimBlockPreamble() |
| | { |
| | if (m_version > 12) { |
| | std::string blockName("*"); |
| | blockName += getLayerName(); |
| | m_saveBlkRecordHandle = getBlkRecordHandle(); |
| | addBlockName(blockName, m_saveBlkRecordHandle); |
| | } |
| |
|
| | m_currentBlock = getBlockHandle(); |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "BLOCK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | (*m_ssBlock) << m_currentBlock << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_saveBlkRecordHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockBegin" << endl; |
| | } |
| | (*m_ssBlock) << " 2" << endl; |
| | (*m_ssBlock) << "*" << getLayerName() << endl; |
| | (*m_ssBlock) << " 70" << endl; |
| | (*m_ssBlock) << " 1" << endl; |
| | (*m_ssBlock) << " 10" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 20" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 30" << endl; |
| | (*m_ssBlock) << 0.0 << endl; |
| | (*m_ssBlock) << " 3" << endl; |
| | (*m_ssBlock) << "*" << getLayerName() << endl; |
| | (*m_ssBlock) << " 1" << endl; |
| | (*m_ssBlock) << " " << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeBlockTrailer() |
| | { |
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "ENDBLK" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | (*m_ssBlock) << getBlockHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_saveBlkRecordHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | } |
| | |
| | |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << getLayerName() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbBlockEnd" << endl; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeLinearDimBlock( |
| | const double* textMidPoint, |
| | const double* lineDefPoint, |
| | const double* extLine1, |
| | const double* extLine2, |
| | const char* dimText, |
| | int type |
| | ) |
| | { |
| | Base::Vector3d e1S(MakeVector3d(extLine1)); |
| | Base::Vector3d e2S(MakeVector3d(extLine2)); |
| | |
| | Base::Vector3d dl(MakeVector3d(lineDefPoint)); |
| | Base::Vector3d perp = dl.DistanceToLineSegment(e2S, e1S); |
| | Base::Vector3d e1E = e1S - perp; |
| | Base::Vector3d e2E = e2S - perp; |
| | Base::Vector3d para = e1E - e2E; |
| | if (type == ALIGNED) { |
| | |
| | } |
| | else if (type == HORIZONTAL) { |
| | double x = extLine1[0]; |
| | double y = lineDefPoint[1]; |
| | e1E = Base::Vector3d(x, y, 0.0); |
| | x = extLine2[0]; |
| | e2E = Base::Vector3d(x, y, 0.0); |
| | perp = Base::Vector3d(0, -1, 0); |
| | para = Base::Vector3d(1, 0, 0); |
| | if (lineDefPoint[1] > extLine1[1]) { |
| | perp = Base::Vector3d(0, 1, 0); |
| | } |
| | if (extLine1[0] > extLine2[0]) { |
| | para = Base::Vector3d(-1, 0, 0); |
| | } |
| | } |
| | else if (type == VERTICAL) { |
| | double x = lineDefPoint[0]; |
| | double y = extLine1[1]; |
| | e1E = Base::Vector3d(x, y, 0.0); |
| | y = extLine2[1]; |
| | e2E = Base::Vector3d(x, y, 0.0); |
| | perp = Base::Vector3d(1, 0, 0); |
| | para = Base::Vector3d(0, 1, 0); |
| | if (lineDefPoint[0] < extLine1[0]) { |
| | perp = Base::Vector3d(-1, 0, 0); |
| | } |
| | if (extLine1[1] > extLine2[1]) { |
| | para = Base::Vector3d(0, -1, 0); |
| | } |
| | } |
| |
|
| | double arrowLen = 5.0; |
| | double arrowWidth = arrowLen / 6.0 / 2.0; |
| |
|
| | putLine(e2S, e2E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | putLine(e1S, e1E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | putLine(e1E, e2E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | putText( |
| | dimText, |
| | toVector3d(textMidPoint), |
| | toVector3d(lineDefPoint), |
| | 3.5, |
| | 1, |
| | m_ssBlock, |
| | getBlockHandle(), |
| | m_saveBlkRecordHandle |
| | ); |
| |
|
| | perp.Normalize(); |
| | para.Normalize(); |
| | Base::Vector3d arrowStart = e1E; |
| | Base::Vector3d barb1 = arrowStart + perp * arrowWidth - para * arrowLen; |
| | Base::Vector3d barb2 = arrowStart - perp * arrowWidth - para * arrowLen; |
| | putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| |
|
| | arrowStart = e2E; |
| | barb1 = arrowStart + perp * arrowWidth + para * arrowLen; |
| | barb2 = arrowStart - perp * arrowWidth + para * arrowLen; |
| | putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeAngularDimBlock( |
| | const double* textMidPoint, |
| | const double* lineDefPoint, |
| | const double* startExt1, |
| | const double* endExt1, |
| | const double* startExt2, |
| | const double* endExt2, |
| | const char* dimText |
| | ) |
| | { |
| | Base::Vector3d e1S(MakeVector3d(startExt1)); |
| | Base::Vector3d e2S(MakeVector3d(startExt2)); |
| | Base::Vector3d e1E(MakeVector3d(endExt1)); |
| | Base::Vector3d e2E(MakeVector3d(endExt2)); |
| | Base::Vector3d e1 = e1E - e1S; |
| | Base::Vector3d e2 = e2E - e2S; |
| |
|
| | double startAngle = atan2(e2.y, e2.x); |
| | double endAngle = atan2(e1.y, e1.x); |
| | double span = fabs(endAngle - startAngle); |
| | double offset = span * 0.10; |
| | if (startAngle < 0) { |
| | startAngle += 2 * std::numbers::pi; |
| | } |
| | if (endAngle < 0) { |
| | endAngle += 2 * std::numbers::pi; |
| | } |
| | Base::Vector3d startOff(cos(startAngle + offset), sin(startAngle + offset), 0.0); |
| | Base::Vector3d endOff(cos(endAngle - offset), sin(endAngle - offset), 0.0); |
| | startAngle = Base::toDegrees(startAngle); |
| | endAngle = Base::toDegrees(endAngle); |
| |
|
| | Base::Vector3d linePt(MakeVector3d(lineDefPoint)); |
| | double radius = (e2S - linePt).Length(); |
| |
|
| | (*m_ssBlock) << " 0" << endl; |
| | (*m_ssBlock) << "ARC" << endl; |
| | (*m_ssBlock) << " 5" << endl; |
| | (*m_ssBlock) << getBlockHandle() << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "330" << endl; |
| | (*m_ssBlock) << m_saveBlkRecordHandle << endl; |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbEntity" << endl; |
| | } |
| | (*m_ssBlock) << " 8" << endl; |
| | (*m_ssBlock) << "0" << endl; |
| | |
| | |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbCircle" << endl; |
| | } |
| | (*m_ssBlock) << " 10" << endl; |
| | (*m_ssBlock) << startExt2[0] << endl; |
| | (*m_ssBlock) << " 20" << endl; |
| | (*m_ssBlock) << startExt2[1] << endl; |
| | (*m_ssBlock) << " 30" << endl; |
| | (*m_ssBlock) << startExt2[2] << endl; |
| | (*m_ssBlock) << " 40" << endl; |
| | (*m_ssBlock) << radius << endl; |
| | if (m_version > 12) { |
| | (*m_ssBlock) << "100" << endl; |
| | (*m_ssBlock) << "AcDbArc" << endl; |
| | } |
| | (*m_ssBlock) << " 50" << endl; |
| | (*m_ssBlock) << startAngle << endl; |
| | (*m_ssBlock) << " 51" << endl; |
| | (*m_ssBlock) << endAngle << endl; |
| |
|
| | putText( |
| | dimText, |
| | toVector3d(textMidPoint), |
| | toVector3d(textMidPoint), |
| | 3.5, |
| | 1, |
| | m_ssBlock, |
| | getBlockHandle(), |
| | m_saveBlkRecordHandle |
| | ); |
| |
|
| | e1.Normalize(); |
| | e2.Normalize(); |
| | Base::Vector3d arrow1Start = e1S + e1 * radius; |
| | Base::Vector3d arrow2Start = e2S + e2 * radius; |
| |
|
| | |
| | Base::Vector3d endTan = e1S + (startOff * radius); |
| | Base::Vector3d startTan = e2S + (endOff * radius); |
| | Base::Vector3d tanP1 = (arrow1Start - startTan).Normalize(); |
| | Base::Vector3d perp1(-tanP1.y, tanP1.x, tanP1.z); |
| | Base::Vector3d tanP2 = (arrow2Start - endTan).Normalize(); |
| | Base::Vector3d perp2(-tanP2.y, tanP2.x, tanP2.z); |
| | double arrowLen = 5.0; |
| | double arrowWidth = arrowLen / 6.0 / 2.0; |
| |
|
| | Base::Vector3d barb1 = arrow1Start + perp1 * arrowWidth - tanP1 * arrowLen; |
| | Base::Vector3d barb2 = arrow1Start - perp1 * arrowWidth - tanP1 * arrowLen; |
| |
|
| | putArrow(arrow1Start, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | barb1 = arrow2Start + perp2 * arrowWidth - tanP2 * arrowLen; |
| | barb2 = arrow2Start - perp2 * arrowWidth - tanP2 * arrowLen; |
| |
|
| | putArrow(arrow2Start, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeRadialDimBlock( |
| | const double* centerPoint, |
| | const double* textMidPoint, |
| | const double* arcPoint, |
| | const char* dimText |
| | ) |
| | { |
| | putLine( |
| | toVector3d(centerPoint), |
| | toVector3d(arcPoint), |
| | m_ssBlock, |
| | getBlockHandle(), |
| | m_saveBlkRecordHandle |
| | ); |
| |
|
| | putText( |
| | dimText, |
| | toVector3d(textMidPoint), |
| | toVector3d(textMidPoint), |
| | 3.5, |
| | 1, |
| | m_ssBlock, |
| | getBlockHandle(), |
| | m_saveBlkRecordHandle |
| | ); |
| |
|
| | Base::Vector3d center(MakeVector3d(centerPoint)); |
| | Base::Vector3d a(MakeVector3d(arcPoint)); |
| | Base::Vector3d para = a - center; |
| | double arrowLen = 5.0; |
| | double arrowWidth = arrowLen / 6.0 / 2.0; |
| | para.Normalize(); |
| | Base::Vector3d perp(-para.y, para.x, para.z); |
| | Base::Vector3d arrowStart = a; |
| | Base::Vector3d barb1 = arrowStart + perp * arrowWidth - para * arrowLen; |
| | Base::Vector3d barb2 = arrowStart - perp * arrowWidth - para * arrowLen; |
| |
|
| | putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeDiametricDimBlock( |
| | const double* textMidPoint, |
| | const double* arcPoint1, |
| | const double* arcPoint2, |
| | const char* dimText |
| | ) |
| | { |
| | putLine(toVector3d(arcPoint1), toVector3d(arcPoint2), m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | putText( |
| | dimText, |
| | toVector3d(textMidPoint), |
| | toVector3d(textMidPoint), |
| | 3.5, |
| | 1, |
| | m_ssBlock, |
| | getBlockHandle(), |
| | m_saveBlkRecordHandle |
| | ); |
| |
|
| | Base::Vector3d a1(MakeVector3d(arcPoint1)); |
| | Base::Vector3d a2(MakeVector3d(arcPoint2)); |
| | Base::Vector3d para = a2 - a1; |
| | double arrowLen = 5.0; |
| | double arrowWidth = arrowLen / 6.0 / 2.0; |
| | para.Normalize(); |
| | Base::Vector3d perp(-para.y, para.x, para.z); |
| | Base::Vector3d arrowStart = a1; |
| | Base::Vector3d barb1 = arrowStart + perp * arrowWidth + para * arrowLen; |
| | Base::Vector3d barb2 = arrowStart - perp * arrowWidth + para * arrowLen; |
| |
|
| | putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| |
|
| | arrowStart = a2; |
| | barb1 = arrowStart + perp * arrowWidth - para * arrowLen; |
| | barb2 = arrowStart - perp * arrowWidth - para * arrowLen; |
| | putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeBlocksSection() |
| | { |
| | if (m_version < 14) { |
| | std::stringstream ss; |
| | ss << "blocks1" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| | } |
| |
|
| | |
| | (*m_ofs) << (*m_ssBlock).str(); |
| |
|
| | (*m_ofs) << " 0" << endl; |
| | (*m_ofs) << "ENDSEC" << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeEntitiesSection() |
| | { |
| | std::stringstream ss; |
| | ss << "entities" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| |
|
| | |
| | (*m_ofs) << (*m_ssEntity).str(); |
| |
|
| |
|
| | (*m_ofs) << " 0" << endl; |
| | (*m_ofs) << "ENDSEC" << endl; |
| | } |
| |
|
| | |
| | |
| | |
| | void CDxfWrite::writeObjectsSection() |
| | { |
| | if (m_version < 14) { |
| | return; |
| | } |
| | std::stringstream ss; |
| | ss << "objects" << m_version << ".rub"; |
| | std::string fileSpec = m_dataDir + ss.str(); |
| | (*m_ofs) << getPlateFile(fileSpec); |
| | } |
| |
|
| | const DxfUnits DxfUnits::Instance; |
| |
|
| | CDxfRead::CDxfRead(const std::string& filepath) |
| | : m_ifs(new ifstream(filepath)) |
| | { |
| | if (!(*m_ifs)) { |
| | m_fail = true; |
| | ImportError("DXF file didn't load\n"); |
| | return; |
| | } |
| | m_ifs->imbue(std::locale("C")); |
| | } |
| |
|
| | CDxfRead::~CDxfRead() |
| | { |
| | delete m_ifs; |
| | |
| | for (auto& pair : Layers) { |
| | delete pair.second; |
| | } |
| | } |
| |
|
| | |
| | const std::string CDxfRead::LineTypeByLayer("BYLAYER"); |
| | const std::string CDxfRead::LineTypeByBlock("BYBLOCK"); |
| | const std::string CDxfRead::DefaultLineType("CONTINUOUS"); |
| |
|
| | |
| | |
| | void CDxfRead::Setup3DVectorAttribute(eDXFGroupCode_t x_record_type, Base::Vector3d& destination) |
| | { |
| | SetupScaledDoubleAttribute((eDXFGroupCode_t)(x_record_type + eXOffset), destination.x); |
| | SetupScaledDoubleAttribute((eDXFGroupCode_t)(x_record_type + eYOffset), destination.y); |
| | SetupScaledDoubleAttribute((eDXFGroupCode_t)(x_record_type + eZOffset), destination.z); |
| | } |
| | void CDxfRead::Setup3DCoordinatesIntoLists( |
| | eDXFGroupCode_t x_record_type, |
| | list<double>& x_destination, |
| | list<double>& y_destination, |
| | list<double>& z_destination |
| | ) |
| | { |
| | SetupScaledDoubleIntoList((eDXFGroupCode_t)(x_record_type + eXOffset), x_destination); |
| | SetupScaledDoubleIntoList((eDXFGroupCode_t)(x_record_type + eYOffset), y_destination); |
| | SetupScaledDoubleIntoList((eDXFGroupCode_t)(x_record_type + eZOffset), z_destination); |
| | } |
| | void CDxfRead::SetupScaledDoubleAttribute(eDXFGroupCode_t x_record_type, double& destination) |
| | { |
| | m_coordinate_attributes.emplace(x_record_type, std::pair(&ProcessScaledDouble, &destination)); |
| | } |
| | void CDxfRead::SetupScaledDoubleIntoList(eDXFGroupCode_t x_record_type, list<double>& destination) |
| | { |
| | m_coordinate_attributes.emplace( |
| | x_record_type, |
| | std::pair(&ProcessScaledDoubleIntoList, &destination) |
| | ); |
| | } |
| | void CDxfRead::Setup3DDirectionAttribute(eDXFGroupCode_t x_record_type, Base::Vector3d& destination) |
| | { |
| | SetupValueAttribute((eDXFGroupCode_t)(x_record_type + eXOffset), destination.x); |
| | SetupValueAttribute((eDXFGroupCode_t)(x_record_type + eYOffset), destination.y); |
| | SetupValueAttribute((eDXFGroupCode_t)(x_record_type + eZOffset), destination.z); |
| | } |
| | void CDxfRead::SetupStringAttribute(eDXFGroupCode_t x_record_type, std::string& destination) |
| | { |
| | m_coordinate_attributes.emplace(x_record_type, std::pair(&ProcessStdString, &destination)); |
| | } |
| | template<typename T> |
| | void CDxfRead::SetupValueAttribute(eDXFGroupCode_t record_type, T& destination) |
| | { |
| | m_coordinate_attributes.emplace(record_type, std::pair(&ProcessValue<T>, &destination)); |
| | } |
| |
|
| | |
| | |
| | void CDxfRead::ProcessScaledDouble(CDxfRead* object, void* target) |
| | { |
| | std::istringstream ss; |
| | ss.imbue(std::locale("C")); |
| |
|
| | ss.str(object->m_record_data); |
| | double value = 0; |
| | ss >> value; |
| | if (ss.fail()) { |
| | object->ImportError( |
| | "Unable to parse value '%s', using zero as its value\n", |
| | object->m_record_data |
| | ); |
| | } |
| | *static_cast<double*>(target) = object->mm(value); |
| | } |
| | void CDxfRead::ProcessScaledDoubleIntoList(CDxfRead* object, void* target) |
| | { |
| | std::istringstream ss; |
| | ss.imbue(std::locale("C")); |
| |
|
| | ss.str(object->m_record_data); |
| | double value = 0; |
| | ss >> value; |
| | if (ss.fail()) { |
| | object->ImportError( |
| | "Unable to parse value '%s', using zero as its value\n", |
| | object->m_record_data |
| | ); |
| | } |
| | static_cast<std::list<double>*>(target)->push_back(object->mm(value)); |
| | } |
| | template<typename T> |
| | bool CDxfRead::ParseValue(CDxfRead* object, void* target) |
| | { |
| | std::istringstream ss; |
| | ss.imbue(std::locale("C")); |
| |
|
| | ss.str(object->m_record_data); |
| | ss >> *static_cast<T*>(target); |
| | if (ss.fail()) { |
| | object->ImportError( |
| | "Unable to parse value '%s', using zero as its value\n", |
| | object->m_record_data |
| | ); |
| | *static_cast<T*>(target) = 0; |
| | return false; |
| | } |
| | |
| | return true; |
| | } |
| | void CDxfRead::ProcessStdString(CDxfRead* object, void* target) |
| | { |
| | *static_cast<std::string*>(target) = object->m_record_data; |
| | } |
| |
|
| | void CDxfRead::InitializeAttributes() |
| | { |
| | m_coordinate_attributes.clear(); |
| | } |
| | bool CDxfRead::ProcessAttribute() |
| | { |
| | auto found = m_coordinate_attributes.find(m_record_type); |
| | if (found != m_coordinate_attributes.end()) { |
| | (*found->second.first)(this, found->second.second); |
| | return true; |
| | } |
| | return false; |
| | } |
| | void CDxfRead::ProcessAllAttributes() |
| | { |
| | while (get_next_record() && m_record_type != eObjectType) { |
| | ProcessAttribute(); |
| | } |
| | repeat_last_record(); |
| | } |
| | void CDxfRead::ProcessAllEntityAttributes() |
| | { |
| | ProcessAllAttributes(); |
| | ResolveEntityAttributes(); |
| | } |
| | void CDxfRead::ResolveEntityAttributes() |
| | { |
| | m_entityAttributes.ResolveBylayerAttributes(*this); |
| | if (m_entityAttributes.m_paperSpace) { |
| | m_stats.entityCounts["ENTITIES_IN_PAPERSPACE"]++; |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | if (EntityNormalVector.IsNull()) { |
| | ImportError("Entity has zero-length extrusion direction\n"); |
| | } |
| | EntityNormalVector.Normalize(); |
| | |
| | |
| | |
| | |
| | |
| | |
| | Base::Vector3d xDirection; |
| | if (EntityNormalVector.x < ArbitraryAxisAlgorithmThreshold |
| | && EntityNormalVector.y < ArbitraryAxisAlgorithmThreshold) { |
| | |
| | static const Base::Vector3d UCSYAxis(0, 1, 0); |
| | xDirection = UCSYAxis % EntityNormalVector; |
| | } |
| | else { |
| | |
| | static const Base::Vector3d UCSZAxis(0, 0, 1); |
| | xDirection = UCSZAxis % EntityNormalVector; |
| | } |
| | OCSOrientationTransform.setCol(0, xDirection); |
| | |
| | |
| | OCSOrientationTransform.setCol(1, EntityNormalVector % xDirection); |
| | |
| | OCSOrientationTransform.setCol(2, EntityNormalVector); |
| | } |
| |
|
| | |
| | |
| | |
| | bool CDxfRead::ReadLine() |
| | { |
| | Base::Vector3d start; |
| | Base::Vector3d end; |
| | Setup3DVectorAttribute(ePrimaryPoint, start); |
| | Setup3DVectorAttribute(ePoint2, end); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadLine(start, end, LineTypeIsHidden()); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadPoint() |
| | { |
| | Base::Vector3d location; |
| | Setup3DVectorAttribute(ePrimaryPoint, location); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadPoint(location); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadArc() |
| | { |
| | double start_angle_degrees = 0; |
| | double end_angle_degrees = 0; |
| | double radius = 0; |
| | Base::Vector3d centre; |
| | Base::Vector3d extrusionDirection(0, 0, 1); |
| |
|
| | Setup3DVectorAttribute(ePrimaryPoint, centre); |
| | SetupScaledDoubleAttribute(eFloat1, radius); |
| | SetupValueAttribute(eAngleDegrees1, start_angle_degrees); |
| | SetupValueAttribute(eAngleDegrees2, end_angle_degrees); |
| | Setup3DVectorAttribute(eExtrusionDirection, extrusionDirection); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadArc( |
| | start_angle_degrees, |
| | end_angle_degrees, |
| | radius, |
| | centre, |
| | extrusionDirection.z, |
| | LineTypeIsHidden() |
| | ); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadSpline() |
| | { |
| | struct SplineData sd; |
| | sd.degree = 0; |
| | sd.knots = 0; |
| | sd.flag = 0; |
| | sd.control_points = 0; |
| | sd.fit_points = 0; |
| |
|
| | Setup3DVectorAttribute(eExtrusionDirection, sd.norm); |
| | SetupValueAttribute(eInteger1, sd.flag); |
| | SetupValueAttribute(eInteger2, sd.degree); |
| | SetupValueAttribute(eInteger3, sd.knots); |
| | SetupValueAttribute(eInteger4, sd.control_points); |
| | SetupValueAttribute(eInteger5, sd.fit_points); |
| | SetupScaledDoubleIntoList(eFloat1, sd.knot); |
| | SetupScaledDoubleIntoList(eFloat2, sd.weight); |
| | Setup3DCoordinatesIntoLists(ePrimaryPoint, sd.controlx, sd.controly, sd.controlz); |
| | Setup3DCoordinatesIntoLists(ePoint2, sd.fitx, sd.fity, sd.fitz); |
| | Setup3DCoordinatesIntoLists(ePoint3, sd.starttanx, sd.starttany, sd.starttanz); |
| | Setup3DCoordinatesIntoLists(ePoint4, sd.endtanx, sd.endtany, sd.endtanz); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadSpline(sd); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadCircle() |
| | { |
| | double radius = 0.0; |
| | Base::Vector3d centre; |
| |
|
| | Setup3DVectorAttribute(ePrimaryPoint, centre); |
| | SetupScaledDoubleAttribute(eFloat1, radius); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadCircle(centre, radius, LineTypeIsHidden()); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadText() |
| | { |
| | Base::Vector3d insertionPoint; |
| | |
| | double height = 0.03082; |
| | double rotation = 0; |
| | std::string textPrefix; |
| |
|
| | Setup3DVectorAttribute(ePrimaryPoint, insertionPoint); |
| | SetupScaledDoubleAttribute(eFloat1, height); |
| | SetupValueAttribute(eAngleDegrees1, rotation); |
| | while (get_next_record() && m_record_type != eObjectType) { |
| | if (!ProcessAttribute()) { |
| | switch (m_record_type) { |
| | case eExtraText: |
| | |
| | |
| | |
| | |
| | |
| | case ePrimaryText: |
| | |
| | |
| | textPrefix.append(m_record_data); |
| | break; |
| | default: |
| | break; |
| | } |
| | } |
| | } |
| | ResolveEntityAttributes(); |
| |
|
| | if ((this->*stringToUTF8)(textPrefix)) { |
| | OnReadText(insertionPoint, height, textPrefix, rotation); |
| | } |
| | else { |
| | ImportError("Unable to process encoding for TEXT/MTEXT '%s'\n", textPrefix); |
| | } |
| | repeat_last_record(); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadEllipse() |
| | { |
| | Base::Vector3d centre; |
| | Base::Vector3d majorAxisEnd; |
| | double eccentricity = 0; |
| | double startAngleRadians = 0; |
| | double endAngleRadians = 2 * std::numbers::pi; |
| |
|
| | Setup3DVectorAttribute(ePrimaryPoint, centre); |
| | Setup3DVectorAttribute(ePoint2, majorAxisEnd); |
| | SetupValueAttribute(eFloat1, eccentricity); |
| | SetupValueAttribute(eFloat2, startAngleRadians); |
| | SetupValueAttribute(eFloat3, endAngleRadians); |
| | ProcessAllEntityAttributes(); |
| |
|
| | OnReadEllipse(centre, majorAxisEnd, eccentricity, startAngleRadians, endAngleRadians); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadLwPolyLine() |
| | { |
| | VertexInfo currentVertex; |
| | list<VertexInfo> vertices; |
| | int flags = 0; |
| |
|
| | bool have_x = false; |
| | bool have_y = false; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Setup3DVectorAttribute(ePrimaryPoint, currentVertex.location); |
| | SetupValueAttribute(eFloat3, currentVertex.bulge); |
| | SetupValueAttribute(eInteger1, flags); |
| | while (get_next_record() && m_record_type != eObjectType) { |
| | if ((m_record_type == ePrimaryPoint + eXOffset && have_x) |
| | || (m_record_type == ePrimaryPoint + eYOffset && have_y)) { |
| | |
| | vertices.push_back(currentVertex); |
| | currentVertex.location = Base::Vector3d(); |
| | currentVertex.bulge = 0.0; |
| | have_x = m_record_type == ePrimaryPoint + eXOffset; |
| | have_y = m_record_type == ePrimaryPoint + eYOffset; |
| | } |
| | else if (m_record_type == ePrimaryPoint + eXOffset) { |
| | have_x = true; |
| | } |
| | else if (m_record_type == ePrimaryPoint + eYOffset) { |
| | have_y = true; |
| | } |
| | ProcessAttribute(); |
| | } |
| | |
| | |
| | if (have_x || have_y) { |
| | vertices.push_back(currentVertex); |
| | } |
| |
|
| | ResolveEntityAttributes(); |
| |
|
| | OnReadPolyline(vertices, flags); |
| | repeat_last_record(); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadPolyLine() |
| | { |
| | VertexInfo currentVertex; |
| | list<VertexInfo> vertices; |
| | int flags = 0; |
| |
|
| | SetupValueAttribute(eInteger1, flags); |
| | ProcessAllEntityAttributes(); |
| |
|
| | |
| | |
| | |
| | Setup3DVectorAttribute(ePrimaryPoint, currentVertex.location); |
| | SetupValueAttribute(eFloat3, currentVertex.bulge); |
| | while (get_next_record() && m_record_type == eObjectType && IsObjectName("VERTEX")) { |
| | |
| | currentVertex.location = Base::Vector3d(); |
| | currentVertex.bulge = 0.0; |
| | ProcessAllEntityAttributes(); |
| | vertices.push_back(currentVertex); |
| | } |
| | if (!IsObjectName("SEQEND")) { |
| | ImportError("POLYLINE ends with '%s' record rather than 'SEQEND'\n", m_record_data); |
| | repeat_last_record(); |
| | } |
| |
|
| | OnReadPolyline(vertices, flags); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadInsert() |
| | { |
| | Base::Vector3d center; |
| | Base::Vector3d scale(1, 1, 1); |
| | double rotationDegrees = 0.0; |
| | std::string blockName; |
| |
|
| | Setup3DVectorAttribute(ePrimaryPoint, center); |
| | SetupValueAttribute(eFloat2, scale.x); |
| | SetupValueAttribute(eFloat3, scale.y); |
| | SetupValueAttribute(eFloat4, scale.z); |
| | SetupValueAttribute(eAngleDegrees1, rotationDegrees); |
| | SetupStringAttribute(eName, blockName); |
| | ProcessAllEntityAttributes(); |
| | OnReadInsert(center, scale, blockName, Base::toRadians(rotationDegrees)); |
| | return (true); |
| | } |
| |
|
| | bool CDxfRead::ReadDimension() |
| | { |
| | Base::Vector3d start; |
| | Base::Vector3d end; |
| | Base::Vector3d linePosition; |
| | Base::Vector3d textPosition; |
| | double rotation = 0; |
| | int dimensionType = 0; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Setup3DVectorAttribute(ePoint4, start); |
| | Setup3DVectorAttribute(ePoint5, end); |
| | Setup3DVectorAttribute(ePrimaryPoint, linePosition); |
| | Setup3DVectorAttribute(ePoint2, textPosition); |
| | SetupValueAttribute(eAngleDegrees1, rotation); |
| | SetupValueAttribute(eInteger1, dimensionType); |
| | ProcessAllEntityAttributes(); |
| |
|
| | dimensionType &= eTypeMask; |
| | switch ((eDimensionType_t)dimensionType) { |
| | case eLinear: |
| | case eAligned: |
| | OnReadDimension(start, end, linePosition, dimensionType, Base::toRadians(rotation)); |
| | break; |
| | default: |
| | UnsupportedFeature("Dimension type '%d'", dimensionType); |
| | break; |
| | } |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadUnknownEntity() |
| | { |
| | ProcessAllEntityAttributes(); |
| | UnsupportedFeature("Entity type '%s'", m_current_entity_name.c_str()); |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::ReadBlockInfo() |
| | { |
| | int blockType = 0; |
| | std::string blockName; |
| | InitializeAttributes(); |
| | |
| | SetupStringAttribute(eName, blockName); |
| | SetupStringAttribute(eExtraText, blockName); |
| | SetupValueAttribute(eInteger1, blockType); |
| | ProcessAllAttributes(); |
| |
|
| | return OnReadBlock(blockName, blockType); |
| | } |
| | bool CDxfRead::ReadBlockContents() |
| | { |
| | while (get_next_record() && m_record_type == eObjectType && !IsObjectName("ENDBLK")) { |
| | if (IgnoreErrors()) { |
| | try { |
| | if (!ReadEntity()) { |
| | return false; |
| | } |
| | } |
| | catch (...) { |
| | } |
| | } |
| | else { |
| | if (!ReadEntity()) { |
| | return false; |
| | } |
| | } |
| | } |
| | return true; |
| | } |
| | bool CDxfRead::SkipBlockContents() |
| | { |
| | while (get_next_record() && m_record_type == eObjectType && !IsObjectName("ENDBLK")) { |
| | if (IgnoreErrors()) { |
| | try { |
| | ProcessAllAttributes(); |
| | } |
| | catch (...) { |
| | } |
| | } |
| | else { |
| | ProcessAllAttributes(); |
| | } |
| | } |
| | return true; |
| | } |
| |
|
| | template<typename... args> |
| | void CDxfRead::UnsupportedFeature(const char* format, args&&... argValuess) |
| | { |
| | |
| | std::string formattedMessage = fmt::sprintf(format, std::forward<args>(argValuess)...); |
| | m_stats.unsupportedFeatures[formattedMessage].emplace_back( |
| | m_current_entity_line_number, |
| | m_current_entity_handle |
| | ); |
| | } |
| |
|
| | bool CDxfRead::get_next_record() |
| | { |
| | if (m_repeat_last_record) { |
| | m_repeat_last_record = false; |
| | return m_not_eof; |
| | } |
| |
|
| | do { |
| | if ((*m_ifs).eof()) { |
| | m_not_eof = false; |
| | return false; |
| | } |
| |
|
| | std::getline(*m_ifs, m_record_data); |
| | ++m_line; |
| | int temp = 0; |
| | if (!ParseValue<int>(this, &temp)) { |
| | ImportError( |
| | "CDxfRead::get_next_record() Failed to get integer record type from '%s'\n", |
| | m_record_data |
| | ); |
| | return false; |
| | } |
| | m_record_type = (eDXFGroupCode_t)temp; |
| | if ((*m_ifs).eof()) { |
| | return false; |
| | } |
| |
|
| | std::getline(*m_ifs, m_record_data); |
| | ++m_line; |
| | } while (m_record_type == eComment); |
| |
|
| | |
| | |
| | auto last = m_record_data.rbegin(); |
| | if (last != m_record_data.rend() && *last == '\r') { |
| | m_record_data.pop_back(); |
| | } |
| | |
| | |
| | |
| | |
| | return true; |
| | } |
| |
|
| | void CDxfRead::repeat_last_record() |
| | { |
| | m_repeat_last_record = true; |
| | } |
| |
|
| | |
| | |
| | |
| | bool CDxfRead::ExplodePolyline(std::list<VertexInfo>& vertices, int flags) |
| | { |
| | if (vertices.size() < 2) { |
| | |
| | return true; |
| | } |
| |
|
| | bool closed = ((flags & 1) != 0); |
| | auto startVertex = vertices.end(); |
| | if (closed) { |
| | |
| | |
| | --startVertex; |
| | } |
| | for (auto endVertex = vertices.begin(); endVertex != vertices.end(); endVertex++) { |
| | if (startVertex != vertices.end()) { |
| | if (startVertex->bulge != 0.0) { |
| | |
| | double cot = ((1.0 / startVertex->bulge) - startVertex->bulge) / 2; |
| | double cx = ((startVertex->location.x + endVertex->location.x) |
| | - ((endVertex->location.y - startVertex->location.y) * cot)) |
| | / 2; |
| | double cy = ((startVertex->location.y + endVertex->location.y) |
| | + ((endVertex->location.x - startVertex->location.x) * cot)) |
| | / 2; |
| | Base::Vector3d pc(cx, cy, (startVertex->location.z + endVertex->location.z) / 2); |
| | OnReadArc(startVertex->location, endVertex->location, pc, startVertex->bulge >= 0, false); |
| | } |
| | else { |
| | OnReadLine(startVertex->location, endVertex->location, false); |
| | } |
| | } |
| | |
| | |
| | startVertex = endVertex; |
| | } |
| | return true; |
| | } |
| | void CDxfRead::OnReadArc( |
| | double start_angle, |
| | double end_angle, |
| | double radius, |
| | const Base::Vector3d& center, |
| | double z_extrusion_dir, |
| | bool hidden |
| | ) |
| | { |
| | Base::Vector3d temp(center); |
| | |
| | Base::Vector3d start(center); |
| | start.x += radius * cos(Base::toRadians(start_angle)); |
| | start.y += radius * sin(Base::toRadians(start_angle)); |
| | Base::Vector3d end(center); |
| | end.x += radius * cos(Base::toRadians(end_angle)); |
| | end.y += radius * sin(Base::toRadians(end_angle)); |
| | if (z_extrusion_dir < 0) { |
| | |
| | |
| | |
| | |
| | |
| | |
| | temp.x = -temp.x; |
| | start.x = -start.x; |
| | end.x = -end.x; |
| | } |
| | OnReadArc(start, end, temp, true, hidden); |
| | } |
| |
|
| | void CDxfRead::OnReadCircle(const Base::Vector3d& center, double radius, bool hidden) |
| | { |
| | |
| | Base::Vector3d start(center); |
| | start.x += radius; |
| |
|
| | OnReadCircle( |
| | start, |
| | center, |
| | false, |
| | hidden |
| | ); |
| | } |
| |
|
| | |
| | void CDxfRead::OnReadEllipse( |
| | const Base::Vector3d& center, |
| | const Base::Vector3d& majorAxisEnd, |
| | double ratio, |
| | double start_angle, |
| | double end_angle |
| | ) |
| | |
| | { |
| | double major_radius = majorAxisEnd.Length(); |
| | double minor_radius = major_radius * ratio; |
| |
|
| | |
| | |
| |
|
| | double rotation = atan2(majorAxisEnd.y, majorAxisEnd.x); |
| |
|
| |
|
| | OnReadEllipse(center, major_radius, minor_radius, rotation, start_angle, end_angle, true); |
| | } |
| |
|
| | bool CDxfRead::ReadVersion() |
| | { |
| | static const std::vector<std::string> VersionNames = { |
| | |
| | "AC1006", |
| | "AC1009", |
| | "AC1012", |
| | "AC1014", |
| | "AC1015", |
| | "AC1018", |
| | "AC1021", |
| | "AC1024", |
| | "AC1027", |
| | "AC1032" |
| | }; |
| |
|
| | assert(VersionNames.size() == RNewer - ROlder - 1); |
| | get_next_record(); |
| | auto first = VersionNames.cbegin(); |
| | auto last = VersionNames.cend(); |
| | auto found = std::lower_bound(first, last, m_record_data); |
| | if (found == last) { |
| | m_version = RNewer; |
| | } |
| | else if (*found == m_record_data) { |
| | m_version = (eDXFVersion_t)((int)std::distance(first, found) + (ROlder + 1)); |
| | } |
| | else if (found == first) { |
| | m_version = ROlder; |
| | } |
| | else { |
| | m_version = RUnknown; |
| | } |
| |
|
| | m_stats.dxfVersion = m_record_data; |
| |
|
| | return ResolveEncoding(); |
| | } |
| |
|
| | bool CDxfRead::ReadDWGCodePage() |
| | { |
| | get_next_record(); |
| | assert(m_CodePage.empty()); |
| | |
| | m_CodePage = m_record_data; |
| |
|
| | return ResolveEncoding(); |
| | } |
| |
|
| | bool CDxfRead::ResolveEncoding() |
| | { |
| | if (m_version >= R2007) { |
| | m_encoding = "utf_8"; |
| | stringToUTF8 = &CDxfRead::UTF8ToUTF8; |
| | } |
| | else if (m_CodePage.empty()) { |
| | |
| | m_encoding = "cp1252"; |
| | stringToUTF8 = &CDxfRead::GeneralToUTF8; |
| | } |
| | else { |
| | |
| | |
| | |
| | m_encoding = m_CodePage; |
| | std::transform(m_encoding.begin(), m_encoding.end(), m_encoding.begin(), ::tolower); |
| |
|
| | |
| | if (m_encoding == "8859_1") { |
| | m_encoding = "iso-8859-1"; |
| | } |
| |
|
| | |
| | #define ANSI_ENCODING_PREFIX "ansi_" |
| | if (m_encoding.rfind(ANSI_ENCODING_PREFIX, 0) == 0 && m_encoding.rfind("ansi_x3", 0) != 0) { |
| | m_encoding.replace(0, (sizeof ANSI_ENCODING_PREFIX) - 1, "cp"); |
| | } |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Base::PyGILStateLocker lock; |
| | PyObject* pyDecoder = PyCodec_Decoder(m_encoding.c_str()); |
| | if (pyDecoder == nullptr) { |
| | |
| | |
| | |
| | PyErr_Clear(); |
| | return false; |
| | } |
| | PyObject* pyUTF8Decoder = PyCodec_Decoder("utf_8"); |
| | assert(pyUTF8Decoder != nullptr); |
| | if (pyDecoder == pyUTF8Decoder) { |
| | stringToUTF8 = &CDxfRead::UTF8ToUTF8; |
| | } |
| | else { |
| | stringToUTF8 = &CDxfRead::GeneralToUTF8; |
| | } |
| | Py_DECREF(pyDecoder); |
| | Py_DECREF(pyUTF8Decoder); |
| | } |
| |
|
| | m_stats.dxfEncoding = m_encoding; |
| |
|
| | return !m_encoding.empty(); |
| | } |
| |
|
| | |
| | |
| | bool CDxfRead::UTF8ToUTF8(std::string& ) const |
| | { |
| | return true; |
| | } |
| |
|
| | bool CDxfRead::GeneralToUTF8(std::string& encoded) const |
| | { |
| | Base::PyGILStateLocker lock; |
| | PyObject* decoded |
| | = PyUnicode_Decode(encoded.c_str(), (Py_ssize_t)encoded.length(), m_encoding.c_str(), "strict"); |
| | if (decoded == nullptr) { |
| | return false; |
| | } |
| | const char* converted = PyUnicode_AsUTF8(decoded); |
| | |
| | if (converted != nullptr) { |
| | encoded = converted; |
| | } |
| | Py_DECREF(decoded); |
| | return converted != nullptr; |
| | } |
| |
|
| | void CDxfRead::DoRead(const bool ignore_errors ) |
| | { |
| | m_ignore_errors = ignore_errors; |
| | if (m_fail) { |
| | return; |
| | } |
| |
|
| | try { |
| | StartImport(); |
| | |
| | while (get_next_record()) { |
| | if (m_record_type != eObjectType) { |
| | ImportError( |
| | "Found type %d record when expecting start of a SECTION or EOF\n", |
| | (int)m_record_type |
| | ); |
| | continue; |
| | } |
| | if (IsObjectName("EOF")) { |
| | break; |
| | } |
| | if (!IsObjectName("SECTION")) { |
| | ImportError( |
| | "Found %s record when expecting start of a SECTION\n", |
| | m_record_data.c_str() |
| | ); |
| | continue; |
| | } |
| | if (!ReadSection()) { |
| | throw Base::Exception("Failed to read DXF section (returned false)."); |
| | } |
| | } |
| | FinishImport(); |
| | } |
| | catch (const Base::Exception& e) { |
| | |
| | throw; |
| | } |
| | catch (const std::exception& e) { |
| | |
| | |
| | throw Base::Exception(e.what()); |
| | } |
| | catch (...) { |
| | |
| | throw Base::Exception("An unknown, non-standard C++ exception occurred during DXF import."); |
| | } |
| | } |
| |
|
| | bool CDxfRead::ReadSection() |
| | { |
| | if (!get_next_record()) { |
| | throw Base::Exception("Unexpected end of file after SECTION tag."); |
| | } |
| | if (m_record_type != eName) { |
| | ImportError("Ignored SECTION with no name record\n"); |
| | return ReadIgnoredSection(); |
| | } |
| |
|
| | if (IsObjectName("HEADER")) { |
| | if (!ReadHeaderSection()) { |
| | throw Base::Exception("Failed while reading HEADER section."); |
| | } |
| | return true; |
| | } |
| | if (IsObjectName("TABLES")) { |
| | if (!ReadTablesSection()) { |
| | throw Base::Exception("Failed while reading TABLES section."); |
| | } |
| | return true; |
| | } |
| | if (IsObjectName("BLOCKS")) { |
| | if (!ReadBlocksSection()) { |
| | throw Base::Exception("Failed while reading BLOCKS section."); |
| | } |
| | return true; |
| | } |
| | if (IsObjectName("ENTITIES")) { |
| | if (!ReadEntitiesSection()) { |
| | throw Base::Exception("Failed while reading ENTITIES section."); |
| | } |
| | return true; |
| | } |
| |
|
| | if (!ReadIgnoredSection()) { |
| | throw Base::Exception("Failed while reading an unknown/ignored section."); |
| | } |
| |
|
| | return true; |
| | } |
| |
|
| | void CDxfRead::ProcessLayerReference(CDxfRead* object, void* target) |
| | { |
| | if (!object->Layers.contains(object->m_record_data)) { |
| | object->ImportError("First reference to missing Layer '%s'", object->m_record_data); |
| | |
| | |
| | |
| | object->Layers[object->m_record_data] |
| | = object->MakeLayer(object->m_record_data, DefaultColor, std::string(DefaultLineType)); |
| | } |
| | *static_cast<Layer**>(target) = object->Layers.at(object->m_record_data); |
| | } |
| | bool CDxfRead::ReadEntity() |
| | { |
| | m_current_entity_line_number = m_line; |
| | m_current_entity_name = m_record_data; |
| | InitializeAttributes(); |
| | m_entityAttributes.SetDefaults(); |
| | m_current_entity_handle.clear(); |
| | SetupStringAttribute(eHandle, m_current_entity_handle); |
| | EntityNormalVector.Set(0, 0, 1); |
| | Setup3DVectorAttribute(eExtrusionDirection, EntityNormalVector); |
| | SetupStringAttribute(eLinetypeName, m_entityAttributes.m_LineType); |
| | m_coordinate_attributes.emplace( |
| | eLayerName, |
| | std::pair(&ProcessLayerReference, &m_entityAttributes.m_Layer) |
| | ); |
| | SetupValueAttribute( |
| | eCoordinateSpace, |
| | m_entityAttributes.m_paperSpace |
| | ); |
| | |
| | SetupValueAttribute(eColor, m_entityAttributes.m_Color); |
| |
|
| | m_stats.entityCounts[m_record_data]++; |
| |
|
| | |
| | if (IsObjectName("LINE")) { |
| | return ReadLine(); |
| | } |
| | if (IsObjectName("ARC")) { |
| | return ReadArc(); |
| | } |
| | if (IsObjectName("CIRCLE")) { |
| | return ReadCircle(); |
| | } |
| | if (IsObjectName("MTEXT")) { |
| | return ReadText(); |
| | } |
| | if (IsObjectName("TEXT")) { |
| | return ReadText(); |
| | } |
| | if (IsObjectName("ELLIPSE")) { |
| | return ReadEllipse(); |
| | } |
| | if (IsObjectName("SPLINE")) { |
| | return ReadSpline(); |
| | } |
| | if (IsObjectName("LWPOLYLINE")) { |
| | return ReadLwPolyLine(); |
| | } |
| | if (IsObjectName("POLYLINE")) { |
| | return ReadPolyLine(); |
| | } |
| | if (IsObjectName("POINT")) { |
| | return ReadPoint(); |
| | } |
| | if (IsObjectName("INSERT")) { |
| | return ReadInsert(); |
| | } |
| | if (IsObjectName("DIMENSION")) { |
| | return ReadDimension(); |
| | } |
| | return ReadUnknownEntity(); |
| | } |
| |
|
| | bool CDxfRead::ReadHeaderSection() |
| | { |
| | |
| | |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type == eObjectType && IsObjectName("ENDSEC")) { |
| | if (m_unitScalingFactor == 0.0) { |
| | |
| | |
| | m_unitScalingFactor = m_additionalScaling; |
| | m_stats.fileUnits = "Unspecified (Defaulting to 1:1)"; |
| | } |
| | m_stats.finalScalingFactor = m_unitScalingFactor; |
| | return true; |
| | } |
| | if (m_record_type != eVariableName) { |
| | continue; |
| | } |
| |
|
| | |
| | std::string currentVarName = m_record_data; |
| | if (!ReadVariable()) { |
| | |
| | throw Base::Exception("Failed while reading value for HEADER variable: " + currentVarName); |
| | } |
| | } |
| |
|
| | |
| | throw Base::Exception("Unexpected end of file inside HEADER section."); |
| | } |
| |
|
| | bool CDxfRead::ReadVariable() |
| | { |
| | if (IsVariableName("$INSUNITS")) { |
| | get_next_record(); |
| | int varValue = 0; |
| | if (!ParseValue<int>(this, &varValue)) { |
| | ImportError("Failed to get integer from INSUNITS value '%s'\n", m_record_data); |
| | } |
| | else { |
| | auto units = DxfUnits::eDxfUnits_t(varValue); |
| | if (!DxfUnits::IsValid(units)) { |
| | units = DxfUnits::eUnspecified; |
| | } |
| | m_unitScalingFactor = DxfUnits::Factor(units) * m_additionalScaling; |
| | m_stats.scalingSource = "$INSUNITS"; |
| | m_stats.fileUnits = DxfUnitToString(units); |
| | } |
| | return true; |
| | } |
| | if (IsVariableName("$MEASUREMENT")) { |
| | get_next_record(); |
| | int varValue = 1; |
| | if (m_unitScalingFactor == 0.0 && ParseValue<int>(this, &varValue)) { |
| | auto units = (varValue != 0 ? DxfUnits::eMillimeters : DxfUnits::eInches); |
| | m_unitScalingFactor = DxfUnits::Factor(units) * m_additionalScaling; |
| | m_stats.scalingSource = "$MEASUREMENT"; |
| | m_stats.fileUnits = DxfUnitToString(units); |
| | } |
| | return true; |
| | } |
| | if (IsVariableName("$ACADVER")) { |
| | return ReadVersion(); |
| | } |
| | if (IsVariableName("$DWGCODEPAGE")) { |
| | return ReadDWGCodePage(); |
| | } |
| | |
| | return get_next_record(); |
| | } |
| |
|
| | bool CDxfRead::ReadTablesSection() |
| | { |
| | |
| | |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type != eObjectType) { |
| | continue; |
| | } |
| | if (IsObjectName("ENDSEC")) { |
| | return true; |
| | } |
| | if (!IsObjectName("TABLE")) { |
| | continue; |
| | } |
| | get_next_record(); |
| | if (m_record_type != eName) { |
| | ImportError("Found unexpected type %d record instead of table name\n", (int)m_record_type); |
| | } |
| | else if (IsObjectName("LAYER")) { |
| | if (!ReadLayerTable()) { |
| | return false; |
| | } |
| | } |
| | else { |
| | if (!ReadIgnoredTable()) { |
| | return false; |
| | } |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | bool CDxfRead::ReadIgnoredSection() |
| | { |
| | |
| | while (get_next_record()) { |
| | if (m_record_type == eObjectType && IsObjectName("ENDSEC")) { |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | bool CDxfRead::ReadBlocksSection() |
| | { |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type != eObjectType) { |
| | continue; |
| | } |
| | if (IsObjectName("ENDSEC")) { |
| | |
| | return true; |
| | } |
| | if (!IsObjectName("BLOCK")) { |
| | continue; |
| | } |
| | if (!ReadBlockInfo()) { |
| | ImportError("CDxfRead::DoRead() Failed to read block\n"); |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool CDxfRead::ReadEntitiesSection() |
| | { |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type != eObjectType) { |
| | continue; |
| | } |
| | if (IsObjectName("ENDSEC")) { |
| | |
| | return true; |
| | } |
| | if (IgnoreErrors()) { |
| | try { |
| | if (!ReadEntity()) { |
| | return false; |
| | } |
| | } |
| | catch (const Base::Exception& e) { |
| | e.reportException(); |
| | } |
| | catch (...) { |
| | ImportError("CDxfRead::ReadEntity raised unknown exception\n"); |
| | } |
| | } |
| | else { |
| | if (!ReadEntity()) { |
| | return false; |
| | } |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool CDxfRead::ReadLayer() |
| | { |
| | std::string layername; |
| | ColorIndex_t layerColor = DefaultColor; |
| | int layerFlags = 0; |
| | std::string lineTypeName(DefaultLineType); |
| | InitializeAttributes(); |
| |
|
| | SetupStringAttribute(eName, layername); |
| | SetupValueAttribute(eColor, layerColor); |
| | SetupValueAttribute(eInteger1, layerFlags); |
| | SetupStringAttribute(eLinetypeName, lineTypeName); |
| | ProcessAllAttributes(); |
| | if (layername.empty()) { |
| | ImportError("CDxfRead::ReadLayer() - no layer name\n"); |
| | return false; |
| | } |
| | if ((layerFlags & 0x01) != 0) { |
| | |
| | |
| | UnsupportedFeature("Frozen layers"); |
| | } |
| | Layers[layername] = MakeLayer(layername, layerColor, std::move(lineTypeName)); |
| | return true; |
| | } |
| | CDxfRead::Layer* CDxfRead::MakeLayer(const std::string& name, ColorIndex_t color, std::string&& lineType) |
| | { |
| | return new Layer(name, color, std::move(lineType)); |
| | } |
| |
|
| | bool CDxfRead::ReadLayerTable() |
| | { |
| | |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type != eObjectType) { |
| | continue; |
| | } |
| | if (IsObjectName("TABLE") || IsObjectName("ENDSEC")) { |
| | |
| | repeat_last_record(); |
| | return true; |
| | } |
| | if (!IsObjectName("LAYER")) { |
| | continue; |
| | } |
| | if (!ReadLayer()) { |
| | ImportError("CDxfRead::DoRead() Failed to read layer\n"); |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool CDxfRead::ReadIgnoredTable() |
| | { |
| | |
| | |
| | while (get_next_record()) { |
| | if (m_record_type == eObjectType && (IsObjectName("TABLE") || IsObjectName("ENDSEC"))) { |
| | repeat_last_record(); |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | |
| | inline static double level(int distance, double blackLevel) |
| | { |
| | |
| | |
| | |
| | if (distance < 0) { |
| | distance = -distance; |
| | } |
| | |
| | |
| | if (distance > 12) { |
| | distance = 24 - distance; |
| | } |
| | if (distance <= 4) { |
| | |
| | return 1.0; |
| | } |
| | if (distance < 8) { |
| | |
| | return ((8 - distance) + blackLevel * (distance - 4)) / 4; |
| | } |
| | |
| | return blackLevel; |
| | } |
| | inline static Base::Color wheel(int hue, double blackLevel, double multiplier = 1.0) |
| | { |
| | return Base::Color( |
| | (float)(level(hue - 0, blackLevel) * multiplier), |
| | (float)(level(hue - 8, blackLevel) * multiplier), |
| | (float)(level(hue - 16, blackLevel) * multiplier) |
| | ); |
| | } |
| | Base::Color CDxfRead::ObjectColor(ColorIndex_t index) |
| | { |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Base::Color result = Base::Color(); |
| | if (index == 0) { |
| | |
| | |
| | |
| | result = Base::Color(); |
| | } |
| | else if (index < 7) { |
| | result = wheel((index - 1) * 4, 0x00); |
| | } |
| | else if (index == 7) { |
| | |
| | |
| | |
| | result = Base::Color(0.5f, 0.5f, 0.5f); |
| | } |
| | else if (index == 8) { |
| | result = Base::Color(0.5, 0.5, 0.5); |
| | } |
| | else if (index == 9) { |
| | result = Base::Color(0.75, 0.75, 0.75); |
| | } |
| | else if (index >= 250) { |
| | auto brightness = (float)((index - 250 + (255 - index) * 0.2) / 5); |
| | result = Base::Color(brightness, brightness, brightness); |
| | } |
| | else { |
| | static const std::array<float, 5> fades = {1.00F, 0.74F, 0.50F, 0.40F, 0.30F}; |
| | return wheel(index / 10 - 1, (index & 1) != 0 ? 0.69 : 0, fades[(index / 2) % 5]); |
| | } |
| | |
| | |
| | |
| | return result; |
| | } |
| | |
| |
|
| | template void CDxfRead::UnsupportedFeature<>(const char*); |
| |
|