diff --git a/src/base/string_conv.h b/src/base/string_conv.h index 166ccb67..4570ee52 100644 --- a/src/base/string_conv.h +++ b/src/base/string_conv.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -136,6 +137,13 @@ template<> struct StringConv } }; +// std::string_view -> NCollection_Utf8String +template<> struct StringConv { + static auto to(std::string_view str) { + return NCollection_Utf8String(str.data(), static_cast(str.size())); + } +}; + // -- // -- Handle(TCollection_HAsciiString) -> X // -- @@ -180,6 +188,13 @@ template<> struct StringConv { } }; +// std::string -> NCollection_Utf8String +template<> struct StringConv { + static auto to(const std::string& str) { + return NCollection_Utf8String(str.c_str(), static_cast(str.size())); + } +}; + // -- // -- TCollection_AsciiString -> X // -- diff --git a/src/io_dxf/dxf.cpp b/src/io_dxf/dxf.cpp index 730be108..f493b0f6 100644 --- a/src/io_dxf/dxf.cpp +++ b/src/io_dxf/dxf.cpp @@ -9,9 +9,11 @@ //required by windows for M_PI definition # define _USE_MATH_DEFINES #endif +#include #include #include +#include #include "../base/filepath.h" #include "dxf.h" @@ -19,10 +21,52 @@ namespace { template -void safe_strcpy(char (&dst)[N1], const char (&src)[N2]) { +void safe_strcpy(char (&dst)[N1], const char (&src)[N2]) +{ strncpy(dst, src, std::min(N1, N2)); } +class ScopedCLocale { +public: + ScopedCLocale(int category) + : m_category(category), + m_savedLocale(std::setlocale(category, nullptr)) + { + std::setlocale(category, "C"); + } + + ~ScopedCLocale() + { + std::setlocale(m_category, m_savedLocale); + } + +private: + int m_category = 0; + const char* m_savedLocale = nullptr; +}; + +double stringToDouble(const std::string& line) +{ + try { + return std::stod(line); + } catch (...) { + throw std::runtime_error("Failed to fetch double value from line:\n" + line); + } + + return 0.; +} + +int stringToInt(const std::string& line) +{ + try { + return std::stoi(line); + } catch (...) { + throw std::runtime_error("Failed to fetch int value from line:\n" + line); + } + + return 0; +} + } // namespace Base::Vector3d toVector3d(const double* a) @@ -34,27 +78,27 @@ Base::Vector3d toVector3d(const double* a) return result; } -CDxfWrite::CDxfWrite(const char* filepath) : -m_ofs(filepath, std::ios::out), -//TODO: these should probably be parameters in config file -//handles: -//boilerplate 0 - A00 -//used by dxf.cpp A01 - FFFE -//ACAD HANDSEED FFFF - -m_handle(0xA00), //room for 2560 handles in boilerplate files -//m_entityHandle(0x300), //don't need special ranges for handles -//m_layerHandle(0x30), -//m_blockHandle(0x210), -//m_blkRecordHandle(0x110), -m_polyOverride(false), -m_layerName("none") +CDxfWrite::CDxfWrite(const char* filepath) + : m_ofs(filepath, std::ios::out), + //TODO: these should probably be parameters in config file + //handles: + //boilerplate 0 - A00 + //used by dxf.cpp A01 - FFFE + //ACAD HANDSEED FFFF + + m_handle(0xA00), //room for 2560 handles in boilerplate files + //m_entityHandle(0x300), //don't need special ranges for handles + //m_layerHandle(0x30), + //m_blockHandle(0x210), + //m_blkRecordHandle(0x110), + m_polyOverride(false), + m_layerName("none") { // start the file m_fail = false; m_version = 12; - if(!m_ofs) + if (!m_ofs) m_fail = true; else m_ofs.imbue(std::locale::classic()); @@ -64,7 +108,7 @@ CDxfWrite::~CDxfWrite() { } -void CDxfWrite::init(void) +void CDxfWrite::init() { writeHeaderSection(); makeBlockRecordTableHead(); @@ -72,7 +116,7 @@ void CDxfWrite::init(void) } //! assemble pieces into output file -void CDxfWrite::endRun(void) +void CDxfWrite::endRun() { makeLayerTable(); makeBlockRecordTableBody(); @@ -90,7 +134,7 @@ void CDxfWrite::endRun(void) //*************************** //writeHeaderSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeHeaderSection(void) +void CDxfWrite::writeHeaderSection() { std::stringstream ss; #if 0 @@ -117,7 +161,7 @@ void CDxfWrite::writeHeaderSection(void) //*************************** //writeClassesSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeClassesSection(void) +void CDxfWrite::writeClassesSection() { if (m_version < 14) { return; @@ -133,7 +177,7 @@ void CDxfWrite::writeClassesSection(void) //*************************** //writeTablesSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeTablesSection(void) +void CDxfWrite::writeTablesSection() { //static tables section head end content std::stringstream ss; @@ -162,7 +206,7 @@ void CDxfWrite::writeTablesSection(void) //*************************** //makeLayerTable //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::makeLayerTable(void) +void CDxfWrite::makeLayerTable() { std::string tablehash = getLayerHandle(); m_ssLayer << " 0" << std::endl; @@ -230,63 +274,63 @@ void CDxfWrite::makeLayerTable(void) //*************************** //makeBlockRecordTableHead //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::makeBlockRecordTableHead(void) +void CDxfWrite::makeBlockRecordTableHead() { if (m_version < 14) { return; } - std::string tablehash = getBlkRecordHandle(); - m_saveBlockRecordTableHandle = tablehash; - m_ssBlkRecord << " 0" << std::endl; - m_ssBlkRecord << "TABLE" << std::endl; - m_ssBlkRecord << " 2" << std::endl; - m_ssBlkRecord << "BLOCK_RECORD" << std::endl; - m_ssBlkRecord << " 5" << std::endl; - m_ssBlkRecord << tablehash << std::endl; - m_ssBlkRecord << "330" << std::endl; - m_ssBlkRecord << "0" << std::endl; - m_ssBlkRecord << "100" << std::endl; - m_ssBlkRecord << "AcDbSymbolTable" << std::endl; - m_ssBlkRecord << " 70" << std::endl; - m_ssBlkRecord << (m_blockList.size() + 5) << std::endl; - - m_saveModelSpaceHandle = getBlkRecordHandle(); - m_ssBlkRecord << " 0" << std::endl; - m_ssBlkRecord << "BLOCK_RECORD" << std::endl; - m_ssBlkRecord << " 5" << std::endl; - m_ssBlkRecord << m_saveModelSpaceHandle << std::endl; - m_ssBlkRecord << "330" << std::endl; - m_ssBlkRecord << tablehash << std::endl; - m_ssBlkRecord << "100" << std::endl; - m_ssBlkRecord << "AcDbSymbolTableRecord" << std::endl; - m_ssBlkRecord << "100" << std::endl; - m_ssBlkRecord << "AcDbBlockTableRecord" << std::endl; - m_ssBlkRecord << " 2" << std::endl; - m_ssBlkRecord << "*MODEL_SPACE" << std::endl; -// m_ssBlkRecord << " 1" << std::endl; -// m_ssBlkRecord << " " << std::endl; - - m_savePaperSpaceHandle = getBlkRecordHandle(); - m_ssBlkRecord << " 0" << std::endl; - m_ssBlkRecord << "BLOCK_RECORD" << std::endl; - m_ssBlkRecord << " 5" << std::endl; - m_ssBlkRecord << m_savePaperSpaceHandle << std::endl; - m_ssBlkRecord << "330" << std::endl; - m_ssBlkRecord << tablehash << std::endl; - m_ssBlkRecord << "100" << std::endl; - m_ssBlkRecord << "AcDbSymbolTableRecord" << std::endl; - m_ssBlkRecord << "100" << std::endl; - m_ssBlkRecord << "AcDbBlockTableRecord" << std::endl; - m_ssBlkRecord << " 2" << std::endl; - m_ssBlkRecord << "*PAPER_SPACE" << std::endl; -// m_ssBlkRecord << " 1" << std::endl; -// m_ssBlkRecord << " " << std::endl; + std::string tablehash = getBlkRecordHandle(); + m_saveBlockRecordTableHandle = tablehash; + m_ssBlkRecord << " 0" << std::endl; + m_ssBlkRecord << "TABLE" << std::endl; + m_ssBlkRecord << " 2" << std::endl; + m_ssBlkRecord << "BLOCK_RECORD" << std::endl; + m_ssBlkRecord << " 5" << std::endl; + m_ssBlkRecord << tablehash << std::endl; + m_ssBlkRecord << "330" << std::endl; + m_ssBlkRecord << "0" << std::endl; + m_ssBlkRecord << "100" << std::endl; + m_ssBlkRecord << "AcDbSymbolTable" << std::endl; + m_ssBlkRecord << " 70" << std::endl; + m_ssBlkRecord << (m_blockList.size() + 5) << std::endl; + + m_saveModelSpaceHandle = getBlkRecordHandle(); + m_ssBlkRecord << " 0" << std::endl; + m_ssBlkRecord << "BLOCK_RECORD" << std::endl; + m_ssBlkRecord << " 5" << std::endl; + m_ssBlkRecord << m_saveModelSpaceHandle << std::endl; + m_ssBlkRecord << "330" << std::endl; + m_ssBlkRecord << tablehash << std::endl; + m_ssBlkRecord << "100" << std::endl; + m_ssBlkRecord << "AcDbSymbolTableRecord" << std::endl; + m_ssBlkRecord << "100" << std::endl; + m_ssBlkRecord << "AcDbBlockTableRecord" << std::endl; + m_ssBlkRecord << " 2" << std::endl; + m_ssBlkRecord << "*MODEL_SPACE" << std::endl; + // m_ssBlkRecord << " 1" << std::endl; + // m_ssBlkRecord << " " << std::endl; + + m_savePaperSpaceHandle = getBlkRecordHandle(); + m_ssBlkRecord << " 0" << std::endl; + m_ssBlkRecord << "BLOCK_RECORD" << std::endl; + m_ssBlkRecord << " 5" << std::endl; + m_ssBlkRecord << m_savePaperSpaceHandle << std::endl; + m_ssBlkRecord << "330" << std::endl; + m_ssBlkRecord << tablehash << std::endl; + m_ssBlkRecord << "100" << std::endl; + m_ssBlkRecord << "AcDbSymbolTableRecord" << std::endl; + m_ssBlkRecord << "100" << std::endl; + m_ssBlkRecord << "AcDbBlockTableRecord" << std::endl; + m_ssBlkRecord << " 2" << std::endl; + m_ssBlkRecord << "*PAPER_SPACE" << std::endl; + // m_ssBlkRecord << " 1" << std::endl; + // m_ssBlkRecord << " " << std::endl; } - + //*************************** //makeBlockRecordTableBody //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::makeBlockRecordTableBody(void) +void CDxfWrite::makeBlockRecordTableBody() { if (m_version < 14) { return; @@ -306,8 +350,8 @@ void CDxfWrite::makeBlockRecordTableBody(void) m_ssBlkRecord << "AcDbBlockTableRecord" << std::endl; m_ssBlkRecord << " 2" << std::endl; m_ssBlkRecord << b << std::endl; -// m_ssBlkRecord << " 70" << std::endl; -// m_ssBlkRecord << " 0" << std::endl; + // m_ssBlkRecord << " 70" << std::endl; + // m_ssBlkRecord << " 0" << std::endl; iBlkRecord++; } } @@ -315,7 +359,7 @@ void CDxfWrite::makeBlockRecordTableBody(void) //*************************** //makeBlockSectionHead //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::makeBlockSectionHead(void) +void CDxfWrite::makeBlockSectionHead() { m_ssBlock << " 0" << std::endl; m_ssBlock << "SECTION" << std::endl; @@ -432,8 +476,7 @@ std::string CDxfWrite::getPlateFile(const std::string& fileSpec) std::string line; std::ifstream inFile (fpath); - while (!inFile.eof()) - { + while (!inFile.eof()) { std::getline(inFile,line); if (!inFile.eof()) { outString << line << '\n'; @@ -443,7 +486,7 @@ std::string CDxfWrite::getPlateFile(const std::string& fileSpec) return outString.str(); } -std::string CDxfWrite::getHandle(void) +std::string CDxfWrite::getHandle() { m_handle++; std::stringstream ss; @@ -452,24 +495,44 @@ std::string CDxfWrite::getHandle(void) return ss.str(); } -std::string CDxfWrite::getEntityHandle(void) +std::string CDxfWrite::getEntityHandle() { return getHandle(); + // m_entityHandle++; + // std::stringstream ss; + // ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2); + // ss << m_entityHandle; + // return ss.str(); } -std::string CDxfWrite::getLayerHandle(void) +std::string CDxfWrite::getLayerHandle() { return getHandle(); + // m_layerHandle++; + // std::stringstream ss; + // ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2); + // ss << m_layerHandle; + // return ss.str(); } -std::string CDxfWrite::getBlockHandle(void) +std::string CDxfWrite::getBlockHandle() { return getHandle(); + // m_blockHandle++; + // std::stringstream ss; + // ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2); + // ss << m_blockHandle; + // return ss.str(); } -std::string CDxfWrite::getBlkRecordHandle(void) +std::string CDxfWrite::getBlkRecordHandle() { return getHandle(); + // m_blkRecordHandle++; + // std::stringstream ss; + // ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2); + // ss << m_blkRecordHandle; + // return ss.str(); } void CDxfWrite::addBlockName(std::string b, std::string h) @@ -480,8 +543,8 @@ void CDxfWrite::addBlockName(std::string b, std::string h) void CDxfWrite::setLayerName(std::string s) { - m_layerName = s; - m_layerList.push_back(s); + m_layerName = s; + m_layerList.push_back(s); } void CDxfWrite::writeLine(const double* s, const double* e) @@ -489,9 +552,11 @@ void CDxfWrite::writeLine(const double* s, const double* e) putLine(toVector3d(s),toVector3d(e),m_ssEntity, getEntityHandle(), m_saveModelSpaceHandle); } -void CDxfWrite::putLine(const Base::Vector3d& s, const Base::Vector3d& e, - std::ostringstream& outStream, const std::string& handle, - const std::string& ownerHandle) +void CDxfWrite::putLine(const Base::Vector3d& s, + const Base::Vector3d& e, + std::ostringstream& outStream, + const std::string& handle, + const std::string& ownerHandle) { outStream << " 0" << std::endl; outStream << "LINE" << std::endl; @@ -551,11 +616,11 @@ void CDxfWrite::writeLWPolyLine(const LWPolyDataOut &pd) m_ssEntity << pd.Flag << std::endl; m_ssEntity << " 43" << std::endl; m_ssEntity << "0" << std::endl; //Constant width opt -// m_ssEntity << pd.Width << std::endl; //Constant width opt -// m_ssEntity << " 38" << std::endl; -// m_ssEntity << pd.Elev << std::endl; // Elevation -// m_ssEntity << " 39" << std::endl; -// m_ssEntity << pd.Thick << std::endl; // Thickness + // m_ssEntity << pd.Width << std::endl; //Constant width opt + // m_ssEntity << " 38" << std::endl; + // m_ssEntity << pd.Elev << std::endl; // Elevation + // m_ssEntity << " 39" << std::endl; + // m_ssEntity << pd.Thick << std::endl; // Thickness for (auto& p: pd.Verts) { m_ssEntity << " 10" << std::endl; // Vertices m_ssEntity << p.x << std::endl; @@ -574,12 +639,12 @@ void CDxfWrite::writeLWPolyLine(const LWPolyDataOut &pd) m_ssEntity << " 42" << std::endl; m_ssEntity << b << std::endl; } -// m_ssEntity << "210" << std::endl; //Extrusion dir -// m_ssEntity << pd.Extr.x << std::endl; -// m_ssEntity << "220" << std::endl; -// m_ssEntity << pd.Extr.y << std::endl; -// m_ssEntity << "230" << std::endl; -// m_ssEntity << pd.Extr.z << std::endl; + // m_ssEntity << "210" << std::endl; //Extrusion dir + // m_ssEntity << pd.Extr.x << std::endl; + // m_ssEntity << "220" << std::endl; + // m_ssEntity << pd.Extr.y << std::endl; + // m_ssEntity << "230" << std::endl; + // m_ssEntity << pd.Extr.z << std::endl; } //*************************** @@ -671,7 +736,7 @@ void CDxfWrite::writeArc(const double* s, const double* e, const double* c, bool double start_angle = atan2(ay, ax) * 180/M_PI; double end_angle = atan2(by, bx) * 180/M_PI; double radius = sqrt(ax*ax + ay*ay); - if(!dir){ + if (!dir){ double temp = start_angle; start_angle = end_angle; end_angle = temp; @@ -688,9 +753,9 @@ void CDxfWrite::writeArc(const double* s, const double* e, const double* c, bool } m_ssEntity << " 8" << std::endl; // Group code for layer name m_ssEntity << getLayerName() << std::endl; // Layer number -// m_ssEntity << " 62" << std::endl; -// m_ssEntity << " 0" << std::endl; - if (m_version > 12) { + // m_ssEntity << " 62" << std::endl; + // m_ssEntity << " 0" << std::endl; + if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbCircle" << std::endl; } @@ -727,7 +792,7 @@ void CDxfWrite::writeCircle(const double* c, double radius) } m_ssEntity << " 8" << std::endl; // Group code for layer name m_ssEntity << getLayerName() << std::endl; // Layer number - if (m_version > 12) { + if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbCircle" << std::endl; } @@ -735,14 +800,18 @@ void CDxfWrite::writeCircle(const double* c, double radius) m_ssEntity << c[0] << std::endl; // X in WCS coordinates m_ssEntity << " 20" << std::endl; m_ssEntity << c[1] << std::endl; // Y in WCS coordinates -// m_ssEntity << " 30" << std::endl; -// m_ssEntity << c[2] << std::endl; // Z in WCS coordinates + // m_ssEntity << " 30" << std::endl; + // m_ssEntity << c[2] << std::endl; // Z in WCS coordinates m_ssEntity << " 40" << std::endl; // m_ssEntity << radius << std::endl; // Radius } -void CDxfWrite::writeEllipse(const double* c, double major_radius, double minor_radius, - double rotation, double start_angle, double end_angle, +void CDxfWrite::writeEllipse(const double* c, + double major_radius, + double minor_radius, + double rotation, + double start_angle, + double end_angle, bool endIsCW) { double m[3]; @@ -752,7 +821,7 @@ void CDxfWrite::writeEllipse(const double* c, double major_radius, double minor_ double ratio = minor_radius/major_radius; - if(!endIsCW){ //end is NOT CW from start + if (!endIsCW){ //end is NOT CW from start double temp = start_angle; start_angle = end_angle; end_angle = temp; @@ -769,7 +838,7 @@ void CDxfWrite::writeEllipse(const double* c, double major_radius, double minor_ } m_ssEntity << " 8" << std::endl; // Group code for layer name m_ssEntity << getLayerName() << std::endl; // Layer number - if (m_version > 12) { + if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbEllipse" << std::endl; } @@ -787,12 +856,12 @@ void CDxfWrite::writeEllipse(const double* c, double major_radius, double minor_ m_ssEntity << m[2] << std::endl; // Major Z m_ssEntity << " 40" << std::endl; // m_ssEntity << ratio << std::endl; // Ratio -// m_ssEntity << "210" << std::endl; //extrusion dir?? -// m_ssEntity << "0" << std::endl; -// m_ssEntity << "220" << std::endl; -// m_ssEntity << "0" << std::endl; -// m_ssEntity << "230" << std::endl; -// m_ssEntity << "1" << std::endl; + // m_ssEntity << "210" << std::endl; //extrusion dir?? + // m_ssEntity << "0" << std::endl; + // m_ssEntity << "220" << std::endl; + // m_ssEntity << "0" << std::endl; + // m_ssEntity << "230" << std::endl; + // m_ssEntity << "1" << std::endl; m_ssEntity << " 41" << std::endl; m_ssEntity << start_angle << std::endl; // Start angle (radians [0..2pi]) m_ssEntity << " 42" << std::endl; @@ -838,18 +907,18 @@ void CDxfWrite::writeSpline(const SplineDataOut &sd) m_ssEntity << " 74" << std::endl; m_ssEntity << 0 << std::endl; -// m_ssEntity << " 12" << std::endl; -// m_ssEntity << sd.starttan.x << std::endl; -// m_ssEntity << " 22" << std::endl; -// m_ssEntity << sd.starttan.y << std::endl; -// m_ssEntity << " 32" << std::endl; -// m_ssEntity << sd.starttan.z << std::endl; -// m_ssEntity << " 13" << std::endl; -// m_ssEntity << sd.endtan.x << std::endl; -// m_ssEntity << " 23" << std::endl; -// m_ssEntity << sd.endtan.y << std::endl; -// m_ssEntity << " 33" << std::endl; -// m_ssEntity << sd.endtan.z << std::endl; + // m_ssEntity << " 12" << std::endl; + // m_ssEntity << sd.starttan.x << std::endl; + // m_ssEntity << " 22" << std::endl; + // m_ssEntity << sd.starttan.y << std::endl; + // m_ssEntity << " 32" << std::endl; + // m_ssEntity << sd.starttan.z << std::endl; + // m_ssEntity << " 13" << std::endl; + // m_ssEntity << sd.endtan.x << std::endl; + // m_ssEntity << " 23" << std::endl; + // m_ssEntity << sd.endtan.y << std::endl; + // m_ssEntity << " 33" << std::endl; + // m_ssEntity << sd.endtan.z << std::endl; for (auto& k: sd.knot) { m_ssEntity << " 40" << std::endl; @@ -910,21 +979,33 @@ void CDxfWrite::writeVertex(double x, double y, double z) m_ssEntity << 0 << std::endl; } -void CDxfWrite::writeText(const char* text, const double* location1, const double* location2, - const double height, const int horizJust) +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); + putText(text, + toVector3d(location1), + toVector3d(location2), + height, + horizJust, + m_ssEntity, + getEntityHandle(), + m_saveModelSpaceHandle); } //*************************** //putText //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -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 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; @@ -944,8 +1025,8 @@ void CDxfWrite::putText(const char* text, const Base::Vector3d& location1, const outStream << "100" << std::endl; outStream << "AcDbText" << std::endl; } -// outStream << " 39" << std::endl; -// outStream << 0 << std::endl; //thickness + // outStream << " 39" << std::endl; + // outStream << 0 << std::endl; //thickness outStream << " 10" << std::endl; //first alignment point outStream << location1.x << std::endl; outStream << " 20" << std::endl; @@ -956,33 +1037,33 @@ void CDxfWrite::putText(const char* text, const Base::Vector3d& location1, const outStream << height << std::endl; outStream << " 1" << std::endl; outStream << text << std::endl; -// outStream << " 50" << std::endl; -// outStream << 0 << std::endl; //rotation -// outStream << " 41" << std::endl; -// outStream << 1 << std::endl; -// outStream << " 51" << std::endl; -// outStream << 0 << std::endl; + // outStream << " 50" << std::endl; + // outStream << 0 << std::endl; //rotation + // outStream << " 41" << std::endl; + // outStream << 1 << std::endl; + // outStream << " 51" << std::endl; + // outStream << 0 << std::endl; outStream << " 7" << std::endl; outStream << "STANDARD" << std::endl; //style -// outStream << " 71" << std::endl; //default -// outStream << "0" << std::endl; + // outStream << " 71" << std::endl; //default + // outStream << "0" << std::endl; outStream << " 72" << std::endl; outStream << horizJust << std::endl; -//// outStream << " 73" << std::endl; -//// outStream << "0" << std::endl; + //// outStream << " 73" << std::endl; + //// outStream << "0" << std::endl; outStream << " 11" << std::endl; //second alignment point outStream << location2.x << std::endl; outStream << " 21" << std::endl; outStream << location2.y << std::endl; outStream << " 31" << std::endl; outStream << location2.z << std::endl; -// outStream << "210" << std::endl; -// outStream << "0" << std::endl; -// outStream << "220" << std::endl; -// outStream << "0" << std::endl; -// outStream << "230" << std::endl; -// outStream << "1" << std::endl; + // outStream << "210" << std::endl; + // outStream << "0" << std::endl; + // outStream << "220" << std::endl; + // outStream << "0" << std::endl; + // outStream << "230" << std::endl; + // outStream << "1" << std::endl; if (m_version > 12) { outStream << "100" << std::endl; outStream << "AcDbText" << std::endl; @@ -990,8 +1071,11 @@ void CDxfWrite::putText(const char* text, const Base::Vector3d& location1, const } -void CDxfWrite::putArrow(const Base::Vector3d& arrowPos, const Base::Vector3d& barb1Pos, const Base::Vector3d& barb2Pos, - std::ostringstream& outStream, const std::string& handle, +void CDxfWrite::putArrow(const Base::Vector3d& arrowPos, + const Base::Vector3d& barb1Pos, + const Base::Vector3d& barb2Pos, + std::ostringstream& outStream, + const std::string& handle, const std::string& ownerHandle) { outStream << " 0" << std::endl; @@ -1044,9 +1128,12 @@ void CDxfWrite::putArrow(const Base::Vector3d& arrowPos, const Base::Vector3d& b #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) +void CDxfWrite::writeLinearDim(const double* textMidPoint, + const double* lineDefPoint, + const double* extLine1, + const double* extLine2, + const char* dimText, + int type) { m_ssEntity << " 0" << std::endl; m_ssEntity << "DIMENSION" << std::endl; @@ -1083,17 +1170,17 @@ void CDxfWrite::writeLinearDim(const double* textMidPoint, const double* lineDef m_ssEntity << 1 << std::endl; // dimType1 = Aligned } if ( (type == HORIZONTAL) || - (type == VERTICAL) ) { + (type == VERTICAL) ) { m_ssEntity << " 70" << std::endl; m_ssEntity << 32 << std::endl; // dimType0 = Aligned + 32 (bit for unique block)? } -// m_ssEntity << " 71" << std::endl; // not R12 -// m_ssEntity << 1 << std::endl; // attachPoint ??1 = topleft + // m_ssEntity << " 71" << std::endl; // not R12 + // m_ssEntity << 1 << std::endl; // attachPoint ??1 = topleft m_ssEntity << " 1" << std::endl; m_ssEntity << dimText << std::endl; m_ssEntity << " 3" << std::endl; m_ssEntity << "STANDARD" << std::endl; //style -//linear dims + //linear dims if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbAlignedDimension" << std::endl; @@ -1115,27 +1202,27 @@ void CDxfWrite::writeLinearDim(const double* textMidPoint, const double* lineDef m_ssEntity << " 50" << std::endl; m_ssEntity << "90" << std::endl; } - if ( (type == HORIZONTAL) || - (type == VERTICAL) ) { + if ( (type == HORIZONTAL) || (type == VERTICAL) ) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbRotatedDimension" << std::endl; } } writeDimBlockPreamble(); - writeLinearDimBlock(textMidPoint,lineDefPoint, - extLine1, extLine2, - dimText, type); + writeLinearDimBlock(textMidPoint, lineDefPoint, extLine1, extLine2, dimText, type); writeBlockTrailer(); } //*************************** //writeAngularDim //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeAngularDim(const double* textMidPoint, const double* lineDefPoint, - const double* startExt1, const double* endExt1, - const double* startExt2, const double* endExt2, - const char* dimText) +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" << std::endl; m_ssEntity << "DIMENSION" << std::endl; @@ -1172,14 +1259,14 @@ void CDxfWrite::writeAngularDim(const double* textMidPoint, const double* lineDe m_ssEntity << " 70" << std::endl; m_ssEntity << 2 << std::endl; // dimType 2 = Angular 5 = Angular 3 point - // +32 for block?? (not R12) -// m_ssEntity << " 71" << std::endl; // not R12? not required? -// m_ssEntity << 5 << std::endl; // attachPoint 5 = middle + // +32 for block?? (not R12) + // m_ssEntity << " 71" << std::endl; // not R12? not required? + // m_ssEntity << 5 << std::endl; // attachPoint 5 = middle m_ssEntity << " 1" << std::endl; m_ssEntity << dimText << std::endl; m_ssEntity << " 3" << std::endl; m_ssEntity << "STANDARD" << std::endl; //style -//angular dims + //angular dims if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDb2LineAngularDimension" << std::endl; @@ -1212,9 +1299,12 @@ void CDxfWrite::writeAngularDim(const double* textMidPoint, const double* lineDe m_ssEntity << " 36" << std::endl; m_ssEntity << lineDefPoint[2] << std::endl; writeDimBlockPreamble(); - writeAngularDimBlock(textMidPoint, lineDefPoint, - startExt1, endExt1, - startExt2, endExt2, + writeAngularDimBlock(textMidPoint, + lineDefPoint, + startExt1, + endExt1, + startExt2, + endExt2, dimText); writeBlockTrailer(); } @@ -1222,9 +1312,10 @@ void CDxfWrite::writeAngularDim(const double* textMidPoint, const double* lineDe //*************************** //writeRadialDim //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeRadialDim(const double* centerPoint, const double* textMidPoint, - const double* arcPoint, - const char* dimText) +void CDxfWrite::writeRadialDim(const double* centerPoint, + const double* textMidPoint, + const double* arcPoint, + const char* dimText) { m_ssEntity << " 0" << std::endl; m_ssEntity << "DIMENSION" << std::endl; @@ -1258,13 +1349,13 @@ void CDxfWrite::writeRadialDim(const double* centerPoint, const double* textMidP m_ssEntity << textMidPoint[2] << std::endl; m_ssEntity << " 70" << std::endl; m_ssEntity << 4 << std::endl; // dimType 4 = Radius -// m_ssEntity << " 71" << std::endl; // not R12 -// m_ssEntity << 1 << std::endl; // attachPoint 5 = middle center + // m_ssEntity << " 71" << std::endl; // not R12 + // m_ssEntity << 1 << std::endl; // attachPoint 5 = middle center m_ssEntity << " 1" << std::endl; m_ssEntity << dimText << std::endl; m_ssEntity << " 3" << std::endl; m_ssEntity << "STANDARD" << std::endl; //style -//radial dims + //radial dims if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbRadialDimension" << std::endl; @@ -1286,9 +1377,10 @@ void CDxfWrite::writeRadialDim(const double* centerPoint, const double* textMidP //*************************** //writeDiametricDim //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeDiametricDim(const double* textMidPoint, - const double* arcPoint1, const double* arcPoint2, - const char* dimText) +void CDxfWrite::writeDiametricDim(const double* textMidPoint, + const double* arcPoint1, + const double* arcPoint2, + const char* dimText) { m_ssEntity << " 0" << std::endl; m_ssEntity << "DIMENSION" << std::endl; @@ -1322,13 +1414,13 @@ void CDxfWrite::writeDiametricDim(const double* textMidPoint, m_ssEntity << textMidPoint[2] << std::endl; m_ssEntity << " 70" << std::endl; m_ssEntity << 3 << std::endl; // dimType 3 = Diameter -// m_ssEntity << " 71" << std::endl; // not R12 -// m_ssEntity << 5 << std::endl; // attachPoint 5 = middle center + // m_ssEntity << " 71" << std::endl; // not R12 + // m_ssEntity << 5 << std::endl; // attachPoint 5 = middle center m_ssEntity << " 1" << std::endl; m_ssEntity << dimText << std::endl; m_ssEntity << " 3" << std::endl; m_ssEntity << "STANDARD" << std::endl; //style -//diametric dims + //diametric dims if (m_version > 12) { m_ssEntity << "100" << std::endl; m_ssEntity << "AcDbDiametricDimension" << std::endl; @@ -1350,7 +1442,7 @@ void CDxfWrite::writeDiametricDim(const double* textMidPoint, //*************************** //writeDimBlockPreamble //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeDimBlockPreamble(void) +void CDxfWrite::writeDimBlockPreamble() { if (m_version > 12) { std::string blockName("*"); @@ -1395,7 +1487,7 @@ void CDxfWrite::writeDimBlockPreamble(void) //*************************** //writeBlockTrailer //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeBlockTrailer(void) +void CDxfWrite::writeBlockTrailer() { m_ssBlock << " 0" << std::endl; m_ssBlock << "ENDBLK" << std::endl; @@ -1407,8 +1499,8 @@ void CDxfWrite::writeBlockTrailer(void) m_ssBlock << "100" << std::endl; m_ssBlock << "AcDbEntity" << std::endl; } -// m_ssBlock << " 67" << std::endl; -// m_ssBlock << "1" << std::endl; + // m_ssBlock << " 67" << std::endl; + // m_ssBlock << "1" << std::endl; m_ssBlock << " 8" << std::endl; m_ssBlock << getLayerName() << std::endl; if (m_version > 12) { @@ -1420,9 +1512,12 @@ void CDxfWrite::writeBlockTrailer(void) //*************************** //writeLinearDimBlock //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeLinearDimBlock(const double* textMidPoint, const double* dimLine, - const double* e1Start, const double* e2Start, - const char* dimText, int type) +void CDxfWrite::writeLinearDimBlock(const double* textMidPoint, + const double* dimLine, + const double* e1Start, + const double* e2Start, + const char* dimText, + int type) { Base::Vector3d e1S(e1Start[0],e1Start[1],e1Start[2]); Base::Vector3d e2S(e2Start[0],e2Start[1],e2Start[2]); @@ -1436,7 +1531,8 @@ void CDxfWrite::writeLinearDimBlock(const double* textMidPoint, const double* di angle = angle * 180.0 / M_PI; if (type == ALIGNED) { //NOP - } else if (type == HORIZONTAL) { + } + else if (type == HORIZONTAL) { double x = e1Start[0]; double y = dimLine[1]; e1E = Base::Vector3d(x, y, 0.0); @@ -1451,7 +1547,8 @@ void CDxfWrite::writeLinearDimBlock(const double* textMidPoint, const double* di para = Base::Vector3d(-1, 0, 0); //left } angle = 0; - } else if (type == VERTICAL) { + } + else if (type == VERTICAL) { double x = dimLine[0]; double y = e1Start[1]; e1E = Base::Vector3d(x, y, 0.0); @@ -1471,44 +1568,45 @@ void CDxfWrite::writeLinearDimBlock(const double* textMidPoint, const double* di double arrowLen = 5.0; //magic number double arrowWidth = arrowLen/6.0/2.0; //magic number calc! - putLine(e2S, e2E, - m_ssBlock, getBlockHandle(), - m_saveBlkRecordHandle); + putLine(e2S, e2E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); - putLine(e1S, e1E, - m_ssBlock, getBlockHandle(), - m_saveBlkRecordHandle); + putLine(e1S, e1E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); - putLine(e1E, e2E, - m_ssBlock, getBlockHandle(), - m_saveBlkRecordHandle); + putLine(e1E, e2E, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); - putText(dimText,toVector3d(textMidPoint), toVector3d(dimLine),3.5,1, - m_ssBlock,getBlockHandle(),m_saveBlkRecordHandle); + putText(dimText, + toVector3d(textMidPoint), + toVector3d(dimLine), + 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); + 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); + putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); } //*************************** //writeAngularDimBlock //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, const double* lineDefPoint, - const double* startExt1, const double* endExt1, - const double* startExt2, const double* endExt2, - const char* dimText) +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(startExt1[0],startExt1[1],startExt1[2]); //apex Base::Vector3d e2S(startExt2[0],startExt2[1],startExt2[2]); @@ -1522,10 +1620,10 @@ void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, const double* l double span = fabs(endAngle - startAngle); double offset = span * 0.10; if (startAngle < 0) { - startAngle += 2.0 * M_PI; + startAngle += 2.0 * M_PI; } if (endAngle < 0) { - endAngle += 2.0 * M_PI; + endAngle += 2.0 * M_PI; } Base::Vector3d startOff(cos(startAngle + offset),sin(startAngle + offset),0.0); Base::Vector3d endOff(cos(endAngle - offset),sin(endAngle - offset),0.0); @@ -1547,8 +1645,8 @@ void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, const double* l } m_ssBlock << " 8" << std::endl; m_ssBlock << "0" << std::endl; -// m_ssBlock << " 62" << std::endl; -// m_ssBlock << " 0" << std::endl; + // m_ssBlock << " 62" << std::endl; + // m_ssBlock << " 0" << std::endl; if (m_version > 12) { m_ssBlock << "100" << std::endl; m_ssBlock << "AcDbCircle" << std::endl; @@ -1570,8 +1668,14 @@ void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, const double* l m_ssBlock << " 51" << std::endl; m_ssBlock << endAngle << std::endl; //end angle - putText(dimText,toVector3d(textMidPoint), toVector3d(textMidPoint),3.5,1, - m_ssBlock,getBlockHandle(),m_saveBlkRecordHandle); + putText(dimText, + toVector3d(textMidPoint), + toVector3d(textMidPoint), + 3.5, + 1, + m_ssBlock, + getBlockHandle(), + m_saveBlkRecordHandle); e1.Normalize(); e2.Normalize(); @@ -1591,28 +1695,36 @@ void CDxfWrite::writeAngularDimBlock(const double* textMidPoint, const double* l 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); + 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); + putArrow(arrow2Start, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); } //*************************** //writeRadialDimBlock //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeRadialDimBlock(const double* centerPoint, const double* textMidPoint, - const double* arcPoint, const char* dimText) +void CDxfWrite::writeRadialDimBlock(const double* centerPoint, + const double* textMidPoint, + const double* arcPoint, + const char* dimText) { - putLine(toVector3d(centerPoint), toVector3d(arcPoint), - m_ssBlock, getBlockHandle(), + putLine(toVector3d(centerPoint), + toVector3d(arcPoint), + m_ssBlock, + getBlockHandle(), m_saveBlkRecordHandle); - putText(dimText,toVector3d(textMidPoint), toVector3d(textMidPoint),3.5,1, - m_ssBlock,getBlockHandle(),m_saveBlkRecordHandle); + putText(dimText, + toVector3d(textMidPoint), + toVector3d(textMidPoint), + 3.5, + 1, + m_ssBlock, + getBlockHandle(), + m_saveBlkRecordHandle); Base::Vector3d c(centerPoint[0],centerPoint[1],centerPoint[2]); Base::Vector3d a(arcPoint[0],arcPoint[1],arcPoint[2]); @@ -1625,23 +1737,31 @@ void CDxfWrite::writeRadialDimBlock(const double* centerPoint, const double* tex 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); + putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); } //*************************** //writeDiametricDimBlock //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeDiametricDimBlock(const double* textMidPoint, - const double* arcPoint1, const double* arcPoint2, - const char* dimText) +void CDxfWrite::writeDiametricDimBlock(const double* textMidPoint, + const double* arcPoint1, + const double* arcPoint2, + const char* dimText) { - putLine(toVector3d(arcPoint1), toVector3d(arcPoint2), - m_ssBlock, getBlockHandle(), + putLine(toVector3d(arcPoint1), + toVector3d(arcPoint2), + m_ssBlock, + getBlockHandle(), m_saveBlkRecordHandle); - putText(dimText,toVector3d(textMidPoint), toVector3d(textMidPoint),3.5,1, - m_ssBlock,getBlockHandle(),m_saveBlkRecordHandle); + putText(dimText, + toVector3d(textMidPoint), + toVector3d(textMidPoint), + 3.5, + 1, + m_ssBlock, + getBlockHandle(), + m_saveBlkRecordHandle); Base::Vector3d a1(arcPoint1[0],arcPoint1[1],arcPoint1[2]); Base::Vector3d a2(arcPoint2[0],arcPoint2[1],arcPoint2[2]); @@ -1654,21 +1774,18 @@ void CDxfWrite::writeDiametricDimBlock(const double* textMidPoint, 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); + 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); - + putArrow(arrowStart, barb1, barb2, m_ssBlock, getBlockHandle(), m_saveBlkRecordHandle); } //*************************** //writeBlocksSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeBlocksSection(void) +void CDxfWrite::writeBlocksSection() { if (m_version < 14) { std::stringstream ss; @@ -1687,7 +1804,7 @@ void CDxfWrite::writeBlocksSection(void) //*************************** //writeEntitiesSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeEntitiesSection(void) +void CDxfWrite::writeEntitiesSection() { std::stringstream ss; ss << "entities" << m_version << ".rub"; @@ -1705,7 +1822,7 @@ void CDxfWrite::writeEntitiesSection(void) //*************************** //writeObjectsSection //added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project -void CDxfWrite::writeObjectsSection(void) +void CDxfWrite::writeObjectsSection() { if (m_version < 14) { return; @@ -1723,7 +1840,7 @@ CDxfRead::CDxfRead(const char* filepath) memset( m_str, '\0', sizeof(m_str) ); memset( m_unused_line, '\0', sizeof(m_unused_line) ); m_fail = false; - m_aci = 0; + m_ColorIndex = 0; m_eUnits = eMillimeters; m_measurement_inch = false; safe_strcpy(m_layer_name, "0"); // Default layer name @@ -1731,6 +1848,10 @@ CDxfRead::CDxfRead(const char* filepath) memset( m_block_name, '\0', sizeof(m_block_name) ); m_ignore_errors = true; + m_version = RUnknown; + //m_CodePage = nullptr; + //m_encoding = nullptr; + if (!m_ifs) m_fail = true; else @@ -1739,39 +1860,66 @@ CDxfRead::CDxfRead(const char* filepath) CDxfRead::~CDxfRead() { + //delete m_CodePage; + //delete m_encoding; } double CDxfRead::mm( double value ) const { - if(m_measurement_inch) - { + // re #6461 + // this if handles situation of malformed DXF file where + // MEASUREMENT specifies English units, but + // INSUNITS specifies millimeters or is not specified + //(millimeters is our default) + if (m_measurement_inch && (m_eUnits == eMillimeters)) { value *= 25.4; } - switch(m_eUnits) - { - case eUnspecified: return(value); // We don't know any better. - case eInches: return(value * 25.4); - case eFeet: return(value * 25.4 * 12); - case eMiles: return(value * 1609344.0); - case eMillimeters: return(value); - case eCentimeters: return(value * 10.0); - case eMeters: return(value * 1000.0); - case eKilometers: return(value * 1000000.0); - case eMicroinches: return(value * 25.4 / 1000.0); - case eMils: return(value * 25.4 / 1000.0); - case eYards: return(value * 3 * 12 * 25.4); - case eAngstroms: return(value * 0.0000001); - case eNanometers: return(value * 0.000001); - case eMicrons: return(value * 0.001); - case eDecimeters: return(value * 100.0); - case eDekameters: return(value * 10000.0); - case eHectometers: return(value * 100000.0); - case eGigameters: return(value * 1000000000000.0); - case eAstronomicalUnits: return(value * 149597870690000.0); - case eLightYears: return(value * 9454254955500000000.0); - case eParsecs: return(value * 30856774879000000000.0); - default: return(value); // We don't know any better. + switch (m_eUnits) { + case eUnspecified: + return (value * 1.0); // We don't know any better. + case eInches: + return (value * 25.4); + case eFeet: + return (value * 25.4 * 12); + case eMiles: + return (value * 1609344.0); + case eMillimeters: + return (value * 1.0); + case eCentimeters: + return (value * 10.0); + case eMeters: + return (value * 1000.0); + case eKilometers: + return (value * 1000000.0); + case eMicroinches: + return (value * 25.4 / 1000.0); + case eMils: + return (value * 25.4 / 1000.0); + case eYards: + return (value * 3 * 12 * 25.4); + case eAngstroms: + return (value * 0.0000001); + case eNanometers: + return (value * 0.000001); + case eMicrons: + return (value * 0.001); + case eDecimeters: + return (value * 100.0); + case eDekameters: + return (value * 10000.0); + case eHectometers: + return (value * 100000.0); + case eGigameters: + return (value * 1000000000000.0); + case eAstronomicalUnits: + return (value * 149597870690000.0); + case eLightYears: + return (value * 9454254955500000000.0); + case eParsecs: + return (value * 30856774879000000000.0); + default: + return (value * 1.0); // We don't know any better. } // End switch } // End mm() method @@ -1782,95 +1930,130 @@ bool CDxfRead::ReadLine() double e[3] = {0, 0, 0}; bool hidden = false; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadLine()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with line - DerefACI(); - OnReadLine(s, e, hidden); - hidden = false; - return true; - - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with line + ResolveColorIndex(); + OnReadLine(s, e, hidden); + hidden = false; + return true; - case 6: // line style name follows - get_line(); - if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; - break; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; - case 10: - // start x - get_line(); - ss.str(m_str); ss >> s[0]; s[0] = mm(s[0]); if(ss.fail()) return false; - break; - case 20: - // start y - get_line(); - ss.str(m_str); ss >> s[1]; s[1] = mm(s[1]); if(ss.fail()) return false; - break; - case 30: - // start z - get_line(); - ss.str(m_str); ss >> s[2]; s[2] = mm(s[2]); if(ss.fail()) return false; - break; - case 11: - // end x - get_line(); - ss.str(m_str); ss >> e[0]; e[0] = mm(e[0]); if(ss.fail()) return false; - break; - case 21: - // end y - get_line(); - ss.str(m_str); ss >> e[1]; e[1] = mm(e[1]); if(ss.fail()) return false; - break; - case 31: - // end z - get_line(); - ss.str(m_str); ss >> e[2]; e[2] = mm(e[2]); if(ss.fail()) return false; - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + case 6: // line style name follows + get_line(); + if (m_str[0] == 'h' || m_str[0] == 'H') { + hidden = true; + } + break; + + case 10: + // start x + get_line(); + ss.str(m_str); + ss >> s[0]; + s[0] = mm(s[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // start y + get_line(); + ss.str(m_str); + ss >> s[1]; + s[1] = mm(s[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // start z + get_line(); + ss.str(m_str); + ss >> s[2]; + s[2] = mm(s[2]); + if (ss.fail()) { + return false; + } + break; + case 11: + // end x + get_line(); + ss.str(m_str); + ss >> e[0]; + e[0] = mm(e[0]); + if (ss.fail()) { + return false; + } + break; + case 21: + // end y + get_line(); + ss.str(m_str); + ss >> e[1]; + e[1] = mm(e[1]); + if (ss.fail()) { + return false; + } + break; + case 31: + // end z + get_line(); + ss.str(m_str); + ss >> e[2]; + e[2] = mm(e[2]); + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } try { - DerefACI(); + ResolveColorIndex(); OnReadLine(s, e, false); } - catch(...) - { - if (! IgnoreErrors()) throw; // Re-throw the exception. + catch (...) { + if (!IgnoreErrors()) { + throw; // Re-throw the exception. + } } return false; @@ -1880,76 +2063,93 @@ bool CDxfRead::ReadPoint() { double s[3] = {0, 0, 0}; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadPoint()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with line - DerefACI(); - OnReadPoint(s); - return true; - - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with line + ResolveColorIndex(); + OnReadPoint(s); + return true; - case 10: - // start x - get_line(); - ss.str(m_str); ss >> s[0]; s[0] = mm(s[0]); if(ss.fail()) return false; - break; - case 20: - // start y - get_line(); - ss.str(m_str); ss >> s[1]; s[1] = mm(s[1]); if(ss.fail()) return false; - break; - case 30: - // start z - get_line(); - ss.str(m_str); ss >> s[2]; s[2] = mm(s[2]); if(ss.fail()) return false; - break; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; - } + case 10: + // start x + get_line(); + ss.str(m_str); + ss >> s[0]; + s[0] = mm(s[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // start y + get_line(); + ss.str(m_str); + ss >> s[1]; + s[1] = mm(s[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // start z + get_line(); + ss.str(m_str); + ss >> s[2]; + s[2] = mm(s[2]); + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } } try { - DerefACI(); + ResolveColorIndex(); OnReadPoint(s); } - catch(...) - { - if (! IgnoreErrors()) throw; // Re-throw the exception. + catch (...) { + if (!IgnoreErrors()) { + throw; // Re-throw the exception. + } } return false; @@ -1964,94 +2164,129 @@ bool CDxfRead::ReadArc() double z_extrusion_dir = 1.0; bool hidden = false; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadArc()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with arc - DerefACI(); - OnReadArc(start_angle, end_angle, radius, c,z_extrusion_dir, hidden); - hidden = false; - return true; - - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with arc + ResolveColorIndex(); + OnReadArc(start_angle, end_angle, radius, c,z_extrusion_dir, hidden); + hidden = false; + return true; - case 6: // line style name follows - get_line(); - if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; - break; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; - case 10: - // centre x - get_line(); - ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; - break; - case 20: - // centre y - get_line(); - ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; - break; - case 30: - // centre z - get_line(); - ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; - break; - case 40: - // radius - get_line(); - ss.str(m_str); ss >> radius; radius = mm(radius); if(ss.fail()) return false; - break; - case 50: - // start angle - get_line(); - ss.str(m_str); ss >> start_angle; if(ss.fail()) return false; - break; - case 51: - // end angle - get_line(); - ss.str(m_str); ss >> end_angle; if(ss.fail()) return false; - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; + case 6: // line style name follows + get_line(); + if (m_str[0] == 'h' || m_str[0] == 'H') { + hidden = true; + } + break; + case 10: + // centre x + get_line(); + ss.str(m_str); + ss >> c[0]; + c[0] = mm(c[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // centre y + get_line(); + ss.str(m_str); + ss >> c[1]; + c[1] = mm(c[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // centre z + get_line(); + ss.str(m_str); + ss >> c[2]; + c[2] = mm(c[2]); + if (ss.fail()) { + return false; + } + break; + case 40: + // radius + get_line(); + ss.str(m_str); + ss >> radius; + radius = mm(radius); + if (ss.fail()) { + return false; + } + break; + case 50: + // start angle + get_line(); + ss.str(m_str); + ss >> start_angle; + if (ss.fail()) { + return false; + } + break; + case 51: + // end angle + get_line(); + ss.str(m_str); + ss >> end_angle; + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; - case 100: - case 39: - case 210: - case 220: - // skip the next line - get_line(); - break; - case 230: - //Z extrusion direction for arc - get_line(); - ss.str(m_str); ss >> z_extrusion_dir; if(ss.fail()) return false; - break; + case 100: + case 39: + case 210: + case 220: + // skip the next line + get_line(); + break; + case 230: + //Z extrusion direction for arc + get_line(); + ss.str(m_str); + ss >> z_extrusion_dir; + if (ss.fail()) { + return false; + } + break; - default: - // skip the next line - get_line(); - break; + default: + // skip the next line + get_line(); + break; } } - DerefACI(); + ResolveColorIndex(); OnReadArc(start_angle, end_angle, radius, c, z_extrusion_dir, false); return false; } @@ -2070,340 +2305,475 @@ bool CDxfRead::ReadSpline() double temp_double; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadSpline()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with Spline - DerefACI(); - OnReadSpline(sd); - return true; - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - case 210: - // normal x - get_line(); - ss.str(m_str); ss >> sd.norm[0]; if(ss.fail()) return false; - break; - case 220: - // normal y - get_line(); - ss.str(m_str); ss >> sd.norm[1]; if(ss.fail()) return false; - break; - case 230: - // normal z - get_line(); - ss.str(m_str); ss >> sd.norm[2]; if(ss.fail()) return false; - break; - case 70: - // flag - get_line(); - ss.str(m_str); ss >> sd.flag; if(ss.fail()) return false; - break; - case 71: - // degree - get_line(); - ss.str(m_str); ss >> sd.degree; if(ss.fail()) return false; - break; - case 72: - // knots - get_line(); - ss.str(m_str); ss >> sd.knots; if(ss.fail()) return false; - break; - case 73: - // control points - get_line(); - ss.str(m_str); ss >> sd.control_points; if(ss.fail()) return false; - break; - case 74: - // fit points - get_line(); - ss.str(m_str); ss >> sd.fit_points; if(ss.fail()) return false; - break; - case 12: - // starttan x - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.starttanx.push_back(temp_double); - break; - case 22: - // starttan y - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.starttany.push_back(temp_double); - break; - case 32: - // starttan z - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.starttanz.push_back(temp_double); - break; - case 13: - // endtan x - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.endtanx.push_back(temp_double); - break; - case 23: - // endtan y - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.endtany.push_back(temp_double); - break; - case 33: - // endtan z - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.endtanz.push_back(temp_double); - break; - case 40: - // knot - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.knot.push_back(temp_double); - break; - case 41: - // weight - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.weight.push_back(temp_double); - break; - case 10: - // control x - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.controlx.push_back(temp_double); - break; - case 20: - // control y - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.controly.push_back(temp_double); - break; - case 30: - // control z - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.controlz.push_back(temp_double); - break; - case 11: - // fit x - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.fitx.push_back(temp_double); - break; - case 21: - // fit y - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.fity.push_back(temp_double); - break; - case 31: - // fit z - get_line(); - ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; - sd.fitz.push_back(temp_double); - break; - case 42: - case 43: - case 44: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; - } - } - DerefACI(); - OnReadSpline(sd); - return false; -} - - -bool CDxfRead::ReadCircle() -{ - double radius = 0.0; - double c[3] = {0,0,0}; // centre - bool hidden = false; - - while(!m_ifs.eof()) - { - get_line(); - int n; - if(sscanf(m_str, "%d", &n) != 1) - { + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with Spline + ResolveColorIndex(); + OnReadSpline(sd); + return true; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + case 210: + // normal x + get_line(); + ss.str(m_str); + ss >> sd.norm[0]; + if (ss.fail()) { + return false; + } + break; + case 220: + // normal y + get_line(); + ss.str(m_str); + ss >> sd.norm[1]; + if (ss.fail()) { + return false; + } + break; + case 230: + // normal z + get_line(); + ss.str(m_str); + ss >> sd.norm[2]; + if (ss.fail()) { + return false; + } + break; + case 70: + // flag + get_line(); + ss.str(m_str); + ss >> sd.flag; + if (ss.fail()) { + return false; + } + break; + case 71: + // degree + get_line(); + ss.str(m_str); + ss >> sd.degree; + if (ss.fail()) { + return false; + } + break; + case 72: + // knots + get_line(); + ss.str(m_str); + ss >> sd.knots; + if (ss.fail()) { + return false; + } + break; + case 73: + // control points + get_line(); + ss.str(m_str); + ss >> sd.control_points; + if (ss.fail()) { + return false; + } + break; + case 74: + // fit points + get_line(); + ss.str(m_str); + ss >> sd.fit_points; + if (ss.fail()) { + return false; + } + break; + case 12: + // starttan x + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.starttanx.push_back(temp_double); + break; + case 22: + // starttan y + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.starttany.push_back(temp_double); + break; + case 32: + // starttan z + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.starttanz.push_back(temp_double); + break; + case 13: + // endtan x + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.endtanx.push_back(temp_double); + break; + case 23: + // endtan y + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.endtany.push_back(temp_double); + break; + case 33: + // endtan z + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.endtanz.push_back(temp_double); + break; + case 40: + // knot + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.knot.push_back(temp_double); + break; + case 41: + // weight + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.weight.push_back(temp_double); + break; + case 10: + // control x + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.controlx.push_back(temp_double); + break; + case 20: + // control y + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.controly.push_back(temp_double); + break; + case 30: + // control z + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.controlz.push_back(temp_double); + break; + case 11: + // fit x + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.fitx.push_back(temp_double); + break; + case 21: + // fit y + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.fity.push_back(temp_double); + break; + case 31: + // fit z + get_line(); + ss.str(m_str); + ss >> temp_double; + temp_double = mm(temp_double); + if (ss.fail()) { + return false; + } + sd.fitz.push_back(temp_double); + break; + case 42: + case 43: + case 44: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + ResolveColorIndex(); + OnReadSpline(sd); + return false; +} + + +bool CDxfRead::ReadCircle() +{ + double radius = 0.0; + double c[3] = {0,0,0}; // centre + bool hidden = false; + + while (!m_ifs.eof()) { + get_line(); + int n; + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadCircle()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with Circle - DerefACI(); - OnReadCircle(c, radius, hidden); - hidden = false; - return true; - - case 6: // line style name follows - get_line(); - if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with Circle + ResolveColorIndex(); + OnReadCircle(c, radius, hidden); + hidden = false; + return true; - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + case 6: // line style name follows + get_line(); + if (m_str[0] == 'h' || m_str[0] == 'H') { + hidden = true; + } + break; - case 10: - // centre x - get_line(); - ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; - break; - case 20: - // centre y - get_line(); - ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; - break; - case 30: - // centre z - get_line(); - ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; - break; - case 40: - // radius - get_line(); - ss.str(m_str); ss >> radius; radius = mm(radius); if(ss.fail()) return false; - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; + + case 10: + // centre x + get_line(); + ss.str(m_str); + ss >> c[0]; + c[0] = mm(c[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // centre y + get_line(); + ss.str(m_str); + ss >> c[1]; + c[1] = mm(c[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // centre z + get_line(); + ss.str(m_str); + ss >> c[2]; + c[2] = mm(c[2]); + if (ss.fail()) { + return false; + } + break; + case 40: + // radius + get_line(); + ss.str(m_str); + ss >> radius; + radius = mm(radius); + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } - DerefACI(); + ResolveColorIndex(); OnReadCircle(c, radius, false); return false; } - -bool CDxfRead::ReadText() +void CDxfRead::ReadText() { - double c[3]; // coordinate - double height = 0.03082; - double rotation = 0.; // degrees - char text[1024] = {}; + ScopedCLocale _(LC_NUMERIC); - memset( c, 0, sizeof(c) ); - - while(!m_ifs.eof()) - { + DxfText text; + while (!m_ifs.eof()) { get_line(); - int n; - if(sscanf(m_str, "%d", &n) != 1) - { - this->ReportError_readInteger("DXF::ReadText()"); - return false; - } - std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - DerefACI(); - OnReadText(c, height * 25.4 / 72.0, rotation, text); - return(true); - - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + const int n = stringToInt(m_str); + switch (n) { + case 0: + ResolveColorIndex(); + { + size_t pos = text.str.find("\\P", 0); + while (pos != std::string::npos) { + text.str.replace(pos, 2, "\n"); + pos = text.str.find("\\P", pos + 1); + } - case 10: - // centre x - get_line(); - ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; - break; - case 20: - // centre y - get_line(); - ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; - break; - case 30: - // centre z - get_line(); - ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; - break; - case 40: - // text height - get_line(); - ss.str(m_str); ss >> height; height = mm(height); if(ss.fail()) return false; - break; - case 1: - // text - get_line(); - safe_strcpy(text, m_str); - break; + text.str = this->toUtf8(text.str); + OnReadText(text); + } + return; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; - case 50: - // text rotation - get_line(); - ss.str(m_str); ss >> rotation; if(ss.fail()) return false; - break; + case 10: + // centre x + get_line(); + text.point[0] = mm(stringToDouble(m_str)); + break; + case 20: + // centre y + get_line(); + text.point[1] = mm(stringToDouble(m_str)); + break; + case 30: + // centre z + get_line(); + text.point[2] = mm(stringToDouble(m_str)); + break; + case 40: + // text height + get_line(); + text.height = mm(stringToDouble(m_str)) * 25.4 / 72.0; + break; + case 50: + // text rotation + get_line(); + text.rotation = stringToDouble(m_str); + break; + case 3: + // Additional text that goes before the type 1 text + // Note that if breaking the text into type-3 records splits a UFT-8 encoding we do + // the decoding after splicing the lines together. I'm not sure if this actually + // occurs, but handling the text this way will treat this condition properly. + get_line(); + text.str.append(m_str); + break; + case 1: + // final text + get_line(); + text.str.append(m_str); + break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + case 62: + // color index + get_line(); + m_ColorIndex = stringToInt(m_str); + break; + + case 71: { + // attachment point + get_line(); + const int ap = stringToInt(m_str); + if (ap >= 1 && ap <= 9) { + text.attachPoint = static_cast(ap); + } } - } + break; - return false; + case 100: + case 39: + case 210: + case 220: + case 230: + default: + // skip the next line + get_line(); + break; + } + } } @@ -2415,92 +2785,136 @@ bool CDxfRead::ReadEllipse() double start=0; //start of arc double end=0; // end of arc - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadEllipse()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found, so finish with Ellipse - DerefACI(); - OnReadEllipse(c, m, ratio, start, end); - return true; - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found, so finish with Ellipse + ResolveColorIndex(); + OnReadEllipse(c, m, ratio, start, end); + return true; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; - case 10: - // centre x - get_line(); - ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; - break; - case 20: - // centre y - get_line(); - ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; - break; - case 30: - // centre z - get_line(); - ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; - break; - case 11: - // major x - get_line(); - ss.str(m_str); ss >> m[0]; m[0] = mm(m[0]); if(ss.fail()) return false; - break; - case 21: - // major y - get_line(); - ss.str(m_str); ss >> m[1]; m[1] = mm(m[1]); if(ss.fail()) return false; - break; - case 31: - // major z - get_line(); - ss.str(m_str); ss >> m[2]; m[2] = mm(m[2]); if(ss.fail()) return false; - break; - case 40: - // ratio - get_line(); - ss.str(m_str); ss >> ratio; if(ss.fail()) return false; - break; - case 41: - // start - get_line(); - ss.str(m_str); ss >> start; if(ss.fail()) return false; - break; - case 42: - // end - get_line(); - ss.str(m_str); ss >> end; if(ss.fail()) return false; - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - case 100: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + case 10: + // centre x + get_line(); + ss.str(m_str); + ss >> c[0]; + c[0] = mm(c[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // centre y + get_line(); + ss.str(m_str); + ss >> c[1]; + c[1] = mm(c[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // centre z + get_line(); + ss.str(m_str); + ss >> c[2]; + c[2] = mm(c[2]); + if (ss.fail()) { + return false; + } + break; + case 11: + // major x + get_line(); + ss.str(m_str); + ss >> m[0]; + m[0] = mm(m[0]); + if (ss.fail()) { + return false; + } + break; + case 21: + // major y + get_line(); + ss.str(m_str); + ss >> m[1]; + m[1] = mm(m[1]); + if (ss.fail()) { + return false; + } + break; + case 31: + // major z + get_line(); + ss.str(m_str); + ss >> m[2]; + m[2] = mm(m[2]); + if (ss.fail()) { + return false; + } + break; + case 40: + // ratio + get_line(); + ss.str(m_str); + ss >> ratio; + if (ss.fail()) { + return false; + } + break; + case 41: + // start + get_line(); + ss.str(m_str); + ss >> start; + if (ss.fail()) { + return false; + } + break; + case 42: + // end + get_line(); + ss.str(m_str); + ss >> end; + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + case 100: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } - DerefACI(); + ResolveColorIndex(); OnReadEllipse(c, m, ratio, start, end); return false; } @@ -2517,15 +2931,14 @@ static double poly_first_x; static double poly_first_y; static double poly_first_z; -static void AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, bool bulge_found, double bulge) +static void +AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, bool bulge_found, double bulge) { try { - if(poly_prev_found) - { + if (poly_prev_found) { bool arc_done = false; - if(poly_prev_bulge_found) - { + if (poly_prev_bulge_found) { double cot = 0.5 * ((1.0 / poly_prev_bulge) - poly_prev_bulge); double cx = ((poly_prev_x + x) - ((y - poly_prev_y) * cot)) / 2.0; double cy = ((poly_prev_y + y) + ((x - poly_prev_x) * cot)) / 2.0; @@ -2536,8 +2949,7 @@ static void AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, b arc_done = true; } - if(!arc_done) - { + if (!arc_done) { double s[3] = {poly_prev_x, poly_prev_y, poly_prev_z}; double e[3] = {x, y, z}; dxf_read->OnReadLine(s, e, false); @@ -2548,8 +2960,7 @@ static void AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, b poly_prev_x = x; poly_prev_y = y; poly_prev_z = z; - if(!poly_first_found) - { + if (!poly_first_found) { poly_first_x = x; poly_first_y = y; poly_first_z = z; @@ -2558,9 +2969,10 @@ static void AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, b poly_prev_bulge_found = bulge_found; poly_prev_bulge = bulge; } - catch(...) - { - if (! dxf_read->IgnoreErrors()) throw; // Re-throw it. + catch (...) { + if (!dxf_read->IgnoreErrors()) { + throw; // Re-throw it. + } } } @@ -2585,89 +2997,110 @@ bool CDxfRead::ReadLwPolyLine() int flags; bool next_item_found = false; - while(!m_ifs.eof() && !next_item_found) - { + while (!m_ifs.eof() && !next_item_found) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadLwPolyLine()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found - - DerefACI(); - if(x_found && y_found){ - // add point - AddPolyLinePoint(this, x, y, z, bulge_found, bulge); - bulge_found = false; - x_found = false; - y_found = false; - } - next_item_found = true; - break; - case 8: // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; - case 10: - // x - get_line(); - if(x_found && y_found){ - // add point - AddPolyLinePoint(this, x, y, z, bulge_found, bulge); - bulge_found = false; - x_found = false; - y_found = false; - } - ss.str(m_str); ss >> x; x = mm(x); if(ss.fail()) return false; - x_found = true; - break; - case 20: - // y - get_line(); - ss.str(m_str); ss >> y; y = mm(y); if(ss.fail()) return false; - y_found = true; - break; - case 38: - // elevation - get_line(); - ss.str(m_str); ss >> z; z = mm(z); if(ss.fail()) return false; - break; - case 42: - // bulge - get_line(); - ss.str(m_str); ss >> bulge; if(ss.fail()) return false; - bulge_found = true; - break; - case 70: - // flags - get_line(); - if(sscanf(m_str, "%d", &flags) != 1)return false; - closed = ((flags & 1) != 0); - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - default: - // skip the next line - get_line(); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found + + ResolveColorIndex(); + if (x_found && y_found){ + // add point + AddPolyLinePoint(this, x, y, z, bulge_found, bulge); + bulge_found = false; + x_found = false; + y_found = false; + } + next_item_found = true; + break; + case 8: // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; + case 10: + // x + get_line(); + if (x_found && y_found) { + // add point + AddPolyLinePoint(this, x, y, z, bulge_found, bulge); + bulge_found = false; + x_found = false; + y_found = false; + } + ss.str(m_str); + ss >> x; + x = mm(x); + if (ss.fail()) { + return false; + } + x_found = true; + break; + case 20: + // y + get_line(); + ss.str(m_str); + ss >> y; + y = mm(y); + if (ss.fail()) { + return false; + } + y_found = true; + break; + case 38: + // elevation + get_line(); + ss.str(m_str); + ss >> z; + z = mm(z); + if (ss.fail()) { + return false; + } + break; + case 42: + // bulge + get_line(); + ss.str(m_str); + ss >> bulge; + if (ss.fail()) { + return false; + } + bulge_found = true; + break; + case 70: + // flags + get_line(); + if (sscanf(m_str, "%d", &flags) != 1) { + return false; + } + closed = ((flags & 1) != 0); + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + default: + // skip the next line + get_line(); + break; } } - if(next_item_found) - { - if(closed && poly_first_found) - { + if (next_item_found) { + if (closed && poly_first_found) { // repeat the first point - DerefACI(); + ResolveColorIndex(); AddPolyLinePoint(this, poly_first_x, poly_first_y, poly_first_z, false, 0.0); } return true; @@ -2692,7 +3125,7 @@ bool CDxfRead::ReadVertex(double *pVertex, bool *bulge_found, double *bulge) pVertex[1] = 0.0; pVertex[2] = 0.0; - while(!m_ifs.eof()) { + while (!m_ifs.eof()) { get_line(); int n; if(sscanf(m_str, "%d", &n) != 1) { @@ -2700,12 +3133,12 @@ bool CDxfRead::ReadVertex(double *pVertex, bool *bulge_found, double *bulge) return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ + ss.imbue(std::locale::classic()); + switch (n){ case 0: - DerefACI(); + ResolveColorIndex(); put_line(m_str); // read one line too many. put it back. - return(x_found && y_found); + return (x_found && y_found); break; case 8: // Layer name follows @@ -2716,31 +3149,54 @@ bool CDxfRead::ReadVertex(double *pVertex, bool *bulge_found, double *bulge) case 10: // x get_line(); - ss.str(m_str); ss >> x; pVertex[0] = mm(x); if(ss.fail()) return false; + ss.str(m_str); + ss >> x; + pVertex[0] = mm(x); + if (ss.fail()) { + return false; + } x_found = true; break; case 20: // y get_line(); - ss.str(m_str); ss >> y; pVertex[1] = mm(y); if(ss.fail()) return false; + ss.str(m_str); + ss >> y; + pVertex[1] = mm(y); + if (ss.fail()) { + return false; + } y_found = true; break; case 30: // z get_line(); - ss.str(m_str); ss >> z; pVertex[2] = mm(z); if(ss.fail()) return false; + ss.str(m_str); + ss >> z; + pVertex[2] = mm(z); + if (ss.fail()) { + return false; + } break; case 42: get_line(); *bulge_found = true; - ss.str(m_str); ss >> *bulge; if(ss.fail()) return false; + ss.str(m_str); + ss >> *bulge; + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; default: // skip the next line @@ -2753,7 +3209,6 @@ bool CDxfRead::ReadVertex(double *pVertex, bool *bulge_found, double *bulge) } - bool CDxfRead::ReadPolyLine() { PolyLineStart(); @@ -2765,115 +3220,133 @@ bool CDxfRead::ReadPolyLine() bool bulge_found; double bulge; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadPolyLine()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found - DerefACI(); - get_line(); - if (! strcmp(m_str,"VERTEX")) - { - double vertex[3] = {0,0,0}; - if (CDxfRead::ReadVertex(vertex, &bulge_found, &bulge)) - { - if(!first_vertex_section_found) { - first_vertex_section_found = true; - memcpy(first_vertex, vertex, 3*sizeof(double)); - } - AddPolyLinePoint(this, vertex[0], vertex[1], vertex[2], bulge_found, bulge); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found + ResolveColorIndex(); + get_line(); + if (!strcmp(m_str, "VERTEX")) { + double vertex[3] = {0,0,0}; + if (CDxfRead::ReadVertex(vertex, &bulge_found, &bulge)) { + if (!first_vertex_section_found) { + first_vertex_section_found = true; + memcpy(first_vertex, vertex, 3*sizeof(double)); } + AddPolyLinePoint(this, vertex[0], vertex[1], vertex[2], bulge_found, bulge); + break; } - if (! strcmp(m_str,"SEQEND")) - { - if(closed && first_vertex_section_found) { - AddPolyLinePoint(this, first_vertex[0], first_vertex[1], first_vertex[2], 0, 0); - } - first_vertex_section_found = false; - PolyLineStart(); - return(true); + } + if (!strcmp(m_str, "SEQEND")) { + if (closed && first_vertex_section_found) { + AddPolyLinePoint(this, + first_vertex[0], + first_vertex[1], + first_vertex[2], + 0, + 0); } - break; - case 70: - // flags - get_line(); - if(sscanf(m_str, "%d", &flags) != 1)return false; - closed = ((flags & 1) != 0); - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - default: - // skip the next line - get_line(); - break; + first_vertex_section_found = false; + PolyLineStart(); + return (true); + } + break; + case 70: + // flags + get_line(); + if (sscanf(m_str, "%d", &flags) != 1) { + return false; + } + closed = ((flags & 1) != 0); + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + default: + // skip the next line + get_line(); + break; } } return false; } -void CDxfRead::OnReadArc(double start_angle, double end_angle, double radius, const double* c, double z_extrusion_dir, bool hidden){ - double s[3] = {0,0,0}, e[3] = {0,0,0}, temp[3] = {0,0,0}; - if (z_extrusion_dir==1.0) - { - temp[0] =c[0]; - temp[1] =c[1]; - temp[2] =c[2]; - s[0] = c[0] + radius * cos(start_angle * M_PI/180); - s[1] = c[1] + radius * sin(start_angle * M_PI/180); - s[2] = c[2]; - e[0] = c[0] + radius * cos(end_angle * M_PI/180); - e[1] = c[1] + radius * sin(end_angle * M_PI/180); - e[2] = c[2]; - } - else - { - temp[0] =-c[0]; - temp[1] =c[1]; - temp[2] =c[2]; - - e[0] = -(c[0] + radius * cos(start_angle * M_PI/180)); - e[1] = (c[1] + radius * sin(start_angle * M_PI/180)); - e[2] = c[2]; - s[0] = -(c[0] + radius * cos(end_angle * M_PI/180)); - s[1] = (c[1] + radius * sin(end_angle * M_PI/180)); - s[2] = c[2]; - +void CDxfRead::OnReadArc(double start_angle, + double end_angle, + double radius, + const double* c, + double z_extrusion_dir, + bool hidden) +{ + double s[3] = {0, 0, 0}, e[3] = {0, 0, 0}, temp[3] = {0, 0, 0}; + if (z_extrusion_dir == 1.0) { + temp[0] = c[0]; + temp[1] = c[1]; + temp[2] = c[2]; + s[0] = c[0] + radius * cos(start_angle * M_PI / 180); + s[1] = c[1] + radius * sin(start_angle * M_PI / 180); + s[2] = c[2]; + e[0] = c[0] + radius * cos(end_angle * M_PI / 180); + e[1] = c[1] + radius * sin(end_angle * M_PI / 180); + e[2] = c[2]; + } + else { + temp[0] =-c[0]; + temp[1] =c[1]; + temp[2] =c[2]; + + e[0] = -(c[0] + radius * cos(start_angle * M_PI/180)); + e[1] = (c[1] + radius * sin(start_angle * M_PI/180)); + e[2] = c[2]; + s[0] = -(c[0] + radius * cos(end_angle * M_PI/180)); + s[1] = (c[1] + radius * sin(end_angle * M_PI/180)); + s[2] = c[2]; } OnReadArc(s, e, temp, true, hidden); } -void CDxfRead::OnReadCircle(const double* c, double radius, bool hidden){ +void CDxfRead::OnReadCircle(const double* c, double radius, bool hidden) +{ double s[3]; double start_angle = 0; - s[0] = c[0] + radius * cos(start_angle * M_PI/180); - s[1] = c[1] + radius * sin(start_angle * M_PI/180); + s[0] = c[0] + radius * cos(start_angle * M_PI / 180); + s[1] = c[1] + radius * sin(start_angle * M_PI / 180); s[2] = c[2]; - OnReadCircle(s, c, false, hidden); //false to change direction because otherwise the arc length is zero + OnReadCircle(s, + c, + false, + hidden); // false to change direction because otherwise the arc length is zero } -void CDxfRead::OnReadEllipse(const double* c, const double* m, double ratio, double start_angle, double end_angle){ - double major_radius = sqrt(m[0]*m[0] + m[1]*m[1] + m[2]*m[2]); +void CDxfRead::OnReadEllipse(const double* c, + const double* m, + double ratio, + double start_angle, + double end_angle) +{ + double major_radius = sqrt(m[0] * m[0] + m[1] * m[1] + m[2] * m[2]); double minor_radius = major_radius * ratio; - //Since we only support 2d stuff, we can calculate the rotation from the major axis x and y value only, - //since z is zero, major_radius is the vector length + // Since we only support 2d stuff, we can calculate the rotation from the major axis x and y + // value only, since z is zero, major_radius is the vector length - double rotation = atan2(m[1]/major_radius,m[0]/major_radius); + double rotation = atan2(m[1] / major_radius, m[0] / major_radius); OnReadEllipse(c, major_radius, minor_radius, rotation, start_angle, end_angle, true); @@ -2887,85 +3360,118 @@ bool CDxfRead::ReadInsert() double rot = 0.0; // rotation char name[1024] = {0}; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadInsert()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found - DerefACI(); - OnReadInsert(c, s, name, rot * M_PI/180); - return(true); - case 8: - // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; - case 10: - // coord x - get_line(); - ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; - break; - case 20: - // coord y - get_line(); - ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; - break; - case 30: - // coord z - get_line(); - ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; - break; - case 41: - // scale x - get_line(); - ss.str(m_str); ss >> s[0]; if(ss.fail()) return false; - break; - case 42: - // scale y - get_line(); - ss.str(m_str); ss >> s[1]; if(ss.fail()) return false; - break; - case 43: - // scale z - get_line(); - ss.str(m_str); ss >> s[2]; if(ss.fail()) return false; - break; - case 50: - // rotation - get_line(); - ss.str(m_str); ss >> rot; if(ss.fail()) return false; - break; - case 2: - // block name - get_line(); - safe_strcpy(name, m_str); - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found + ResolveColorIndex(); + OnReadInsert(c, s, name, rot * M_PI/180); + return(true); + case 8: + // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; + case 10: + // coord x + get_line(); + ss.str(m_str); + ss >> c[0]; + c[0] = mm(c[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // coord y + get_line(); + ss.str(m_str); + ss >> c[1]; + c[1] = mm(c[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // coord z + get_line(); + ss.str(m_str); + ss >> c[2]; + c[2] = mm(c[2]); + if (ss.fail()) { + return false; + } + break; + case 41: + // scale x + get_line(); + ss.str(m_str); + ss >> s[0]; + if (ss.fail()) { + return false; + } + break; + case 42: + // scale y + get_line(); + ss.str(m_str); + ss >> s[1]; + if (ss.fail()) { + return false; + } + break; + case 43: + // scale z + get_line(); + ss.str(m_str); + ss >> s[2]; + if (ss.fail()) { + return false; + } + break; + case 50: + // rotation + get_line(); + ss.str(m_str); + ss >> rot; + if (ss.fail()) { + return false; + } + break; + case 2: + // block name + get_line(); + strcpy(name, m_str); + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } return false; @@ -2979,95 +3485,146 @@ bool CDxfRead::ReadDimension() double p[3] = {0,0,0}; // dimpoint double rot = -1.0; // rotation - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadDimension()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: - // next item found - DerefACI(); - OnReadDimension(s, e, p, rot * M_PI/180); - return(true); - case 8: - // Layer name follows - get_line(); - safe_strcpy(m_layer_name, m_str); - break; - case 13: - // start x - get_line(); - ss.str(m_str); ss >> s[0]; s[0] = mm(s[0]); if(ss.fail()) return false; - break; - case 23: - // start y - get_line(); - ss.str(m_str); ss >> s[1]; s[1] = mm(s[1]); if(ss.fail()) return false; - break; - case 33: - // start z - get_line(); - ss.str(m_str); ss >> s[2]; s[2] = mm(s[2]); if(ss.fail()) return false; - break; - case 14: - // end x - get_line(); - ss.str(m_str); ss >> e[0]; e[0] = mm(e[0]); if(ss.fail()) return false; - break; - case 24: - // end y - get_line(); - ss.str(m_str); ss >> e[1]; e[1] = mm(e[1]); if(ss.fail()) return false; - break; - case 34: - // end z - get_line(); - ss.str(m_str); ss >> e[2]; e[2] = mm(e[2]); if(ss.fail()) return false; - break; - case 10: - // dimline x - get_line(); - ss.str(m_str); ss >> p[0]; p[0] = mm(p[0]); if(ss.fail()) return false; - break; - case 20: - // dimline y - get_line(); - ss.str(m_str); ss >> p[1]; p[1] = mm(p[1]); if(ss.fail()) return false; - break; - case 30: - // dimline z - get_line(); - ss.str(m_str); ss >> p[2]; p[2] = mm(p[2]); if(ss.fail()) return false; - break; - case 50: - // rotation - get_line(); - ss.str(m_str); ss >> rot; if(ss.fail()) return false; - break; - case 62: - // color index - get_line(); - ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; - break; - case 100: - case 39: - case 210: - case 220: - case 230: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: + // next item found + ResolveColorIndex(); + OnReadDimension(s, e, p, rot * M_PI/180); + return(true); + case 8: + // Layer name follows + get_line(); + safe_strcpy(m_layer_name, m_str); + break; + case 13: + // start x + get_line(); + ss.str(m_str); + ss >> s[0]; + s[0] = mm(s[0]); + if (ss.fail()) { + return false; + } + break; + case 23: + // start y + get_line(); + ss.str(m_str); + ss >> s[1]; + s[1] = mm(s[1]); + if (ss.fail()) { + return false; + } + break; + case 33: + // start z + get_line(); + ss.str(m_str); + ss >> s[2]; + s[2] = mm(s[2]); + if (ss.fail()) { + return false; + } + break; + case 14: + // end x + get_line(); + ss.str(m_str); + ss >> e[0]; + e[0] = mm(e[0]); + if (ss.fail()) { + return false; + } + break; + case 24: + // end y + get_line(); + ss.str(m_str); + ss >> e[1]; + e[1] = mm(e[1]); + if (ss.fail()) { + return false; + } + break; + case 34: + // end z + get_line(); + ss.str(m_str); + ss >> e[2]; + e[2] = mm(e[2]); + if (ss.fail()) { + return false; + } + break; + case 10: + // dimline x + get_line(); + ss.str(m_str); + ss >> p[0]; + p[0] = mm(p[0]); + if (ss.fail()) { + return false; + } + break; + case 20: + // dimline y + get_line(); + ss.str(m_str); + ss >> p[1]; + p[1] = mm(p[1]); + if (ss.fail()) { + return false; + } + break; + case 30: + // dimline z + get_line(); + ss.str(m_str); + ss >> p[2]; + p[2] = mm(p[2]); + if (ss.fail()) { + return false; + } + break; + case 50: + // rotation + get_line(); + ss.str(m_str); + ss >> rot; + if (ss.fail()) { + return false; + } + break; + case 62: + // color index + get_line(); + ss.str(m_str); + ss >> m_ColorIndex; + if (ss.fail()) { + return false; + } + break; + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } return false; @@ -3076,32 +3633,30 @@ bool CDxfRead::ReadDimension() bool CDxfRead::ReadBlockInfo() { - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadBlockInfo()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 2: - // block name - get_line(); - safe_strcpy(m_block_name, m_str); - return true; - case 3: - // block name too??? - get_line(); - safe_strcpy(m_block_name, m_str); - return true; - default: - // skip the next line - get_line(); - break; + ss.imbue(std::locale::classic()); + switch (n){ + case 2: + // block name + get_line(); + safe_strcpy(m_block_name, m_str); + return true; + case 3: + // block name too??? + get_line(); + safe_strcpy(m_block_name, m_str); + return true; + default: + // skip the next line + get_line(); + break; } } return false; @@ -3110,25 +3665,23 @@ bool CDxfRead::ReadBlockInfo() void CDxfRead::get_line() { - if (m_unused_line[0] != '\0') - { + if (m_unused_line[0] != '\0') { safe_strcpy(m_str, m_unused_line); - memset( m_unused_line, '\0', sizeof(m_unused_line)); + memset(m_unused_line, '\0', sizeof(m_unused_line)); return; } m_ifs.getline(m_str, 1024); - ++m_lineNum; char str[1024]; size_t len = strlen(m_str); int j = 0; bool non_white_found = false; - for(size_t i = 0; iReportError_readInteger("DXF::ReadUnits()"); return(false); } @@ -3175,215 +3726,313 @@ bool CDxfRead::ReadUnits() bool CDxfRead::ReadLayer() { std::string layername; - int aci = -1; + ColorIndex_t colorIndex = -1; - while(!m_ifs.eof()) - { + while (!m_ifs.eof()) { get_line(); int n; - if(sscanf(m_str, "%d", &n) != 1) - { + if (sscanf(m_str, "%d", &n) != 1) { this->ReportError_readInteger("DXF::ReadLayer()"); return false; } std::istringstream ss; - ss.imbue(std::locale("C")); - switch(n){ - case 0: // next item found, so finish with line - if (layername.empty()) - return false; + ss.imbue(std::locale::classic()); + switch (n){ + case 0: // next item found, so finish with line + if (layername.empty()) { + this->ReportError_readInteger("DXF::ReadLayer() - no layer name"); + return false; + } + m_layer_ColorIndex_map[layername] = colorIndex; + return true; - m_layer_aci[layername] = aci; - return true; + case 2: // Layer name follows + get_line(); + layername = m_str; + break; - case 2: // Layer name follows - get_line(); - layername = m_str; - break; + case 62: + // layer color ; if negative, layer is off + get_line(); + if (sscanf(m_str, "%d", &colorIndex) != 1) { + return false; + } + break; - case 62: - // layer color ; if negative, layer is off - get_line(); - if(sscanf(m_str, "%d", &aci) != 1)return false; - break; - - case 6: // linetype name - case 70: // layer flags - case 100: - case 290: - case 370: - case 390: - // skip the next line - get_line(); - break; - default: - // skip the next line - get_line(); - break; + case 6: // linetype name + case 70: // layer flags + case 100: + case 290: + case 370: + case 390: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; } } return false; } +bool CDxfRead::ReadVersion() +{ + static const std::vector VersionNames = { + // This table is indexed by eDXFVersion_t - (ROlder+1) + "AC1006", + "AC1009", + "AC1012", + "AC1014", + "AC1015", + "AC1018", + "AC1021", + "AC1024", + "AC1027", + "AC1032"}; + + assert(VersionNames.size() == RNewer - ROlder - 1); + get_line(); + get_line(); + std::vector::const_iterator first = VersionNames.cbegin(); + std::vector::const_iterator last = VersionNames.cend(); + std::vector::const_iterator found = std::lower_bound(first, last, m_str); + if (found == last) { + m_version = RNewer; + } + else if (*found == m_str) { + m_version = (eDXFVersion_t)(std::distance(first, found) + (ROlder + 1)); + } + else if (found == first) { + m_version = ROlder; + } + else { + m_version = RUnknown; + } + + return ResolveEncoding(); +} + +bool CDxfRead::ReadDWGCodePage() +{ + get_line(); + get_line(); + m_CodePage = m_str; + + return ResolveEncoding(); +} + +bool CDxfRead::ResolveEncoding() +{ + // + // See https://ezdxf.readthedocs.io/en/stable/dxfinternals/fileencoding.html# + // + + if (m_version >= R2007) { // Note this does not include RUnknown, but does include RLater + return this->setSourceEncoding("UTF8"); + } + else { + std::transform(m_CodePage.cbegin(), m_CodePage.cend(), m_CodePage.begin(), [](char c) { + return std::toupper(c, std::locale::classic()); + }); + // ANSI_1252 by default if $DWGCODEPAGE is not set + if (m_CodePage.empty()) + m_CodePage = "ANSI_1252"; + + return this->setSourceEncoding(m_CodePage); + } +} + +#if 0 +const char* CDxfRead::UTF8ToUTF8(const char* encoded) const +{ + return encoded; +} + +const char* CDxfRead::GeneralToUTF8(const char* encoded) const +{ + Base::PyGILStateLocker lock; + PyObject* decoded = PyUnicode_Decode(encoded, strlen(encoded), m_encoding->c_str(), "strict"); + if (decoded == nullptr) { + return nullptr; + } + Py_ssize_t len; + const char* converted = PyUnicode_AsUTF8AndSize(decoded, &len); + char* result = nullptr; + if (converted != nullptr) { + // converted only has lifetime of decoded so we must save a copy. + result = (char*)malloc(len + 1); + if (result == nullptr) { + PyErr_SetString(PyExc_MemoryError, "Out of memory"); + } + else { + memcpy(result, converted, len + 1); + } + } + Py_DECREF(decoded); + return result; +} +#endif + void CDxfRead::DoRead(const bool ignore_errors /* = false */ ) { m_ignore_errors = ignore_errors; - if(m_fail)return; + if (m_fail) { + return; + } get_line(); - while(!m_ifs.eof()) - { - m_aci = 256; - - if (!strcmp( m_str, "$INSUNITS" )){ - if (!ReadUnits())return; + while (!m_ifs.eof()) { + if (!strcmp(m_str, "$INSUNITS" )) { + if (!ReadUnits()) { + return; + } continue; } // End if - then - if (!strcmp( m_str, "$MEASUREMENT" )){ + if (!strcmp(m_str, "$MEASUREMENT" )) { get_line(); get_line(); int n = 1; - if(sscanf(m_str, "%d", &n) == 1) - { - if(n == 0)m_measurement_inch = true; + if (sscanf(m_str, "%d", &n) == 1) { + if (n == 0) { + m_measurement_inch = true; + } } continue; } // End if - then - else if(!strcmp(m_str, "0")) - { + if (!strcmp(m_str, "$ACADVER")) { + if (!ReadVersion()) { + return; + } + continue; + } // End if - then + + if (!strcmp(m_str, "$DWGCODEPAGE")) { + if (!ReadDWGCodePage()) { + return; + } + continue; + } // End if - then + + if (!strcmp(m_str, "0")) { get_line(); - if (!strcmp( m_str, "SECTION" )){ - safe_strcpy(m_section_name, ""); - get_line(); - get_line(); - if (strcmp( m_str, "ENTITIES" )) - safe_strcpy(m_section_name, m_str); - safe_strcpy(m_block_name, ""); + if (!strcmp( m_str, "SECTION" )) { + safe_strcpy(m_section_name, ""); + get_line(); + get_line(); + if (strcmp( m_str, "ENTITIES" )) { + safe_strcpy(m_section_name, m_str); + } + safe_strcpy(m_block_name, ""); - } // End if - then - else if (!strcmp( m_str, "TABLE" )){ - get_line(); - get_line(); - } + } // End if - then + else if (!strcmp( m_str, "TABLE" )) { + get_line(); + get_line(); + } - else if (!strcmp( m_str, "LAYER" )){ - if(!ReadLayer()) - { - this->ReportError("DXF::DoRead() - Failed to read layer"); - //return; Some objects or tables can have "LAYER" as name... + else if (!strcmp( m_str, "LAYER" )) { + get_line(); + get_line(); + if (!ReadLayer()) { + this->ReportError("DXF::DoRead() - Failed to read layer"); + //return; Some objects or tables can have "LAYER" as name... } - continue; - } - - else if (!strcmp( m_str, "BLOCK" )) { - if(!ReadBlockInfo()) - { - this->ReportError("DXF::DoRead() - Failed to read block info"); - return; + continue; } - continue; - } // End if - then - else if (!strcmp( m_str, "ENDSEC" )){ - safe_strcpy(m_section_name, ""); - safe_strcpy(m_block_name, ""); - } // End if - then - else if(!strcmp(m_str, "LINE")){ - if(!ReadLine()) - { - this->ReportError("DXF::DoRead() - Failed to read line"); + else if (!strcmp( m_str, "BLOCK" )) { + if (!ReadBlockInfo()) { + this->ReportError("DXF::DoRead() - Failed to read block info"); return; } continue; - } - else if(!strcmp(m_str, "ARC")){ - if(!ReadArc()) - { - this->ReportError("DXF::DoRead() - Failed to read arc"); + } // End if - then + + else if (!strcmp( m_str, "ENDSEC" )) { + safe_strcpy(m_section_name, ""); + safe_strcpy(m_block_name, ""); + } // End if - then + else if (!strcmp(m_str, "LINE")) { + if (!ReadLine()) { + this->ReportError("DXF::DoRead() - Failed to read line"); return; } continue; } - else if(!strcmp(m_str, "CIRCLE")){ - if(!ReadCircle()) - { - this->ReportError("DXF::DoRead() - Failed to read circle"); + else if (!strcmp(m_str, "ARC")) { + if (!ReadArc()) { + this->ReportError("DXF::DoRead() - Failed to read arc"); return; } continue; } - else if(!strcmp(m_str, "MTEXT")){ - if(!ReadText()) - { - this->ReportError("DXF::DoRead() - Failed to read text"); + else if (!strcmp(m_str, "CIRCLE")) { + if (!ReadCircle()) { + this->ReportError("DXF::DoRead() - Failed to read circle"); return; } continue; } - else if(!strcmp(m_str, "TEXT")){ - if(!ReadText()) - { - this->ReportError("DXF::DoRead() - Failed to read text"); + else if (!strcmp(m_str, "MTEXT") || !strcmp(m_str, "TEXT")) { + try { + ReadText(); + } catch (const std::runtime_error& err) { + this->ReportError("DXF::DoRead() - Failed to read text\nError: " + std::string(err.what())); return; } continue; } - else if(!strcmp(m_str, "ELLIPSE")){ - if(!ReadEllipse()) - { + else if (!strcmp(m_str, "ELLIPSE")) { + if (!ReadEllipse()) { this->ReportError("DXF::DoRead() - Failed to read ellipse"); return; } continue; } - else if(!strcmp(m_str, "SPLINE")){ - if(!ReadSpline()) - { + else if (!strcmp(m_str, "SPLINE")) { + if (!ReadSpline()) { this->ReportError("DXF::DoRead() - Failed to read spline"); return; } continue; } else if (!strcmp(m_str, "LWPOLYLINE")) { - if(!ReadLwPolyLine()) - { + if (!ReadLwPolyLine()) { this->ReportError("DXF::DoRead() - Failed to read LW Polyline"); return; } continue; } else if (!strcmp(m_str, "POLYLINE")) { - if(!ReadPolyLine()) - { + if (!ReadPolyLine()) { this->ReportError("DXF::DoRead() - Failed to read Polyline"); return; } continue; } else if (!strcmp(m_str, "POINT")) { - if(!ReadPoint()) - { + if (!ReadPoint()) { this->ReportError("DXF::DoRead() - Failed to read Point"); return; } continue; } else if (!strcmp(m_str, "INSERT")) { - if(!ReadInsert()) - { + if (!ReadInsert()) { this->ReportError("DXF::DoRead() - Failed to read Insert"); return; } continue; } else if (!strcmp(m_str, "DIMENSION")) { - if(!ReadDimension()) - { + if (!ReadDimension()) { this->ReportError("DXF::DoRead() - Failed to read Dimension"); return; } @@ -3397,12 +4046,12 @@ void CDxfRead::DoRead(const bool ignore_errors /* = false */ ) } -void CDxfRead::DerefACI() +void CDxfRead::ResolveColorIndex() { - if (m_aci == 256) // if color = layer color, replace by color from layer + if (m_ColorIndex == ColorBylayer) // if color = layer color, replace by color from layer { - m_aci = m_layer_aci[std::string(m_layer_name)]; + m_ColorIndex = m_layer_ColorIndex_map[std::string(m_layer_name)]; } } @@ -3429,20 +4078,17 @@ std::string CDxfRead::LayerName() const { std::string result; - if (strlen(m_section_name) > 0) - { + if (strlen(m_section_name) > 0) { result.append(m_section_name); result.append(" "); } - if (strlen(m_block_name) > 0) - { + if (strlen(m_block_name) > 0) { result.append(m_block_name); result.append(" "); } - if (strlen(m_layer_name) > 0) - { + if (strlen(m_layer_name) > 0) { result.append(m_layer_name); } diff --git a/src/io_dxf/dxf.h b/src/io_dxf/dxf.h index 9cd8b05e..a21dd629 100644 --- a/src/io_dxf/dxf.h +++ b/src/io_dxf/dxf.h @@ -8,25 +8,23 @@ #pragma once #include +#include +#include +#include +#include +#include #include -#include +#include #include #include -#include #include -#include -#include -#include -#include +#include +#include #include "freecad.h" +#include -//Following is required to be defined on Ubuntu with OCC 6.3.1 -#ifndef HAVE_IOSTREAM -#define HAVE_IOSTREAM -#endif - -typedef int Aci_t; // AutoCAD color index +typedef int ColorIndex_t; // DXF color index typedef enum { @@ -53,6 +51,19 @@ typedef enum eParsecs } eDxfUnits_t; +enum class AttachmentPoint { + TopLeft = 1, TopCenter, TopRight, + MiddleLeft, MiddleCenter, MiddleRight, + BottomLeft, BottomCenter, BottomRight +}; + +struct DxfText { + double point[3] = {}; + double height = 0.03082; + std::string str; + double rotation = 0.; // radians + AttachmentPoint attachPoint = AttachmentPoint::TopLeft; +}; //spline data for reading struct SplineData @@ -118,9 +129,26 @@ struct LWPolyDataOut std::vector Bulge; point3D Extr; }; +typedef enum +{ + RUnknown, + ROlder, + R10, + R11_12, + R13, + R14, + R2000, + R2004, + R2007, + R2010, + R2013, + R2018, + RNewer, +} eDXFVersion_t; //******************** -class CDxfWrite{ +class CDxfWrite +{ private: std::ofstream m_ofs; bool m_fail; @@ -130,29 +158,45 @@ class CDxfWrite{ std::ostringstream m_ssLayer; protected: - void putLine(const Base::Vector3d& s, const Base::Vector3d& e, - std::ostringstream& outStream, const std::string& handle, + void putLine(const Base::Vector3d& s, + const Base::Vector3d& e, + std::ostringstream& outStream, + const std::string& handle, const std::string& ownerHandle); - void 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, + void 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 putArrow(const Base::Vector3d& arrowPos, const Base::Vector3d& barb1Pos, const Base::Vector3d& barb2Pos, - std::ostringstream& outStream, const std::string& handle, + void putArrow(const Base::Vector3d& arrowPos, + const Base::Vector3d& barb1Pos, + const Base::Vector3d& barb2Pos, + std::ostringstream& outStream, + const std::string& handle, const std::string& ownerHandle); //! copy boiler plate file std::string getPlateFile(const std::string& fileSpec); - void setDataDir(const std::string& s) { m_dataDir = s; } - std::string getHandle(void); - std::string getEntityHandle(void); - std::string getLayerHandle(void); - std::string getBlockHandle(void); - std::string getBlkRecordHandle(void); + void setDataDir(const std::string& s) + { + m_dataDir = s; + } + std::string getHandle(); + std::string getEntityHandle(); + std::string getLayerHandle(); + std::string getBlockHandle(); + std::string getBlkRecordHandle(); std::string m_optionSource; int m_version; int m_handle; + int m_entityHandle; + int m_layerHandle; + int m_blockHandle; + int m_blkRecordHandle; bool m_polyOverride; std::string m_saveModelSpaceHandle; @@ -170,74 +214,112 @@ class CDxfWrite{ CDxfWrite(const char* filepath); ~CDxfWrite(); - void init(void); - void endRun(void); + void init(); + void endRun(); - bool Failed(){return m_fail;} + bool Failed() + { + return m_fail; + } // void setOptions(void); // bool isVersionValid(int vers); - std::string getLayerName() { return m_layerName; } + std::string getLayerName() + { + return m_layerName; + } void setLayerName(std::string s); - void setVersion(int v) { m_version = v;} - void setPolyOverride(bool b) { m_polyOverride = b; } + void setVersion(int v) + { + m_version = v; + } + void setPolyOverride(bool b) + { + m_polyOverride = b; + } void addBlockName(std::string s, std::string blkRecordHandle); void writeLine(const double* s, const double* e); void writePoint(const double*); void writeArc(const double* s, const double* e, const double* c, bool dir); - void writeEllipse(const double* c, double major_radius, double minor_radius, - double rotation, double start_angle, double end_angle, bool endIsCW); + void writeEllipse(const double* c, + double major_radius, + double minor_radius, + double rotation, + double start_angle, + double end_angle, + bool endIsCW); void writeCircle(const double* c, double radius ); - void writeSpline(const SplineDataOut &sd); - void writeLWPolyLine(const LWPolyDataOut &pd); - void writePolyline(const LWPolyDataOut &pd); + void writeSpline(const SplineDataOut& sd); + void writeLWPolyLine(const LWPolyDataOut& pd); + void writePolyline(const LWPolyDataOut& pd); void writeVertex(double x, double y, double z); - void writeText(const char* text, const double* location1, const double* location2, - const double height, const int horizJust); - void writeLinearDim(const double* textMidPoint, const double* lineDefPoint, - const double* extLine1, const double* extLine2, - const char* dimText, int type); - void writeLinearDimBlock(const double* textMidPoint, const double* lineDefPoint, - const double* extLine1, const double* extLine2, - const char* dimText, int type); - void writeAngularDim(const double* textMidPoint, const double* lineDefPoint, - const double* startExt1, const double* endExt1, - const double* startExt2, const double* endExt2, - const char* dimText); - void writeAngularDimBlock(const double* textMidPoint, const double* lineDefPoint, - const double* startExt1, const double* endExt1, - const double* startExt2, const double* endExt2, - const char* dimText); - void writeRadialDim(const double* centerPoint, const double* textMidPoint, - const double* arcPoint, - const char* dimText); - void writeRadialDimBlock(const double* centerPoint, const double* textMidPoint, - const double* arcPoint, const char* dimText); - void writeDiametricDim(const double* textMidPoint, - const double* arcPoint1, const double* arcPoint2, - const char* dimText); - void writeDiametricDimBlock(const double* textMidPoint, - const double* arcPoint1, const double* arcPoint2, + void writeText(const char* text, + const double* location1, + const double* location2, + const double height, + const int horizJust); + void writeLinearDim(const double* textMidPoint, + const double* lineDefPoint, + const double* extLine1, + const double* extLine2, + const char* dimText, + int type); + void writeLinearDimBlock(const double* textMidPoint, + const double* lineDefPoint, + const double* extLine1, + const double* extLine2, + const char* dimText, + int type); + void writeAngularDim(const double* textMidPoint, + const double* lineDefPoint, + const double* startExt1, + const double* endExt1, + const double* startExt2, + const double* endExt2, const char* dimText); + void writeAngularDimBlock(const double* textMidPoint, + const double* lineDefPoint, + const double* startExt1, + const double* endExt1, + const double* startExt2, + const double* endExt2, + const char* dimText); + void writeRadialDim(const double* centerPoint, + const double* textMidPoint, + const double* arcPoint, + const char* dimText); + void writeRadialDimBlock(const double* centerPoint, + const double* textMidPoint, + const double* arcPoint, + const char* dimText); + void writeDiametricDim(const double* textMidPoint, + const double* arcPoint1, + const double* arcPoint2, + const char* dimText); + void writeDiametricDimBlock(const double* textMidPoint, + const double* arcPoint1, + const double* arcPoint2, + const char* dimText); void writeDimBlockPreamble(); - void writeBlockTrailer(void); - - void writeHeaderSection(void); - void writeTablesSection(void); - void writeBlocksSection(void); - void writeEntitiesSection(void); - void writeObjectsSection(void); - void writeClassesSection(void); - - void makeLayerTable(void); - void makeBlockRecordTableHead(void); - void makeBlockRecordTableBody(void); - void makeBlockSectionHead(void); + void writeBlockTrailer(); + + void writeHeaderSection(); + void writeTablesSection(); + void writeBlocksSection(); + void writeEntitiesSection(); + void writeObjectsSection(); + void writeClassesSection(); + + void makeLayerTable(); + void makeBlockRecordTableHead(); + void makeBlockRecordTableBody(); + void makeBlockSectionHead(); }; // derive a class from this and implement it's virtual functions -class CDxfRead{ +class CDxfRead +{ private: std::ifstream m_ifs; @@ -252,13 +334,14 @@ class CDxfRead{ bool m_ignore_errors; - typedef std::map< std::string,Aci_t > LayerAciMap_t; - LayerAciMap_t m_layer_aci; // layer names -> layer color aci map + std::map + m_layer_ColorIndex_map; // Mapping from layer name -> layer color index + const ColorIndex_t ColorBylayer = 256; bool ReadUnits(); bool ReadLayer(); bool ReadLine(); - bool ReadText(); + void ReadText(); bool ReadArc(); bool ReadCircle(); bool ReadEllipse(); @@ -267,48 +350,97 @@ class CDxfRead{ bool ReadLwPolyLine(); bool ReadPolyLine(); bool ReadVertex(double *pVertex, bool *bulge_found, double *bulge); - void OnReadArc(double start_angle, double end_angle, double radius, const double* c, double z_extrusion_dir, bool hidden); + void OnReadArc(double start_angle, + double end_angle, + double radius, + const double* c, + double z_extrusion_dir, + bool hidden); void OnReadCircle(const double* c, double radius, bool hidden); - void OnReadEllipse(const double* c, const double* m, double ratio, double start_angle, double end_angle); + void OnReadEllipse(const double* c, + const double* m, + double ratio, + double start_angle, + double end_angle); bool ReadInsert(); bool ReadDimension(); bool ReadBlockInfo(); + bool ReadVersion(); + bool ReadDWGCodePage(); + bool ResolveEncoding(); void put_line(const char *value); - void DerefACI(); + void ResolveColorIndex(); void ReportError_readInteger(const char* context); protected: - Aci_t m_aci; // manifest color name or 256 for layer color - int m_lineNum = 0; + ColorIndex_t m_ColorIndex; + eDXFVersion_t m_version; // Version from $ACADVER variable in DXF std::streamsize gcount() const; virtual void get_line(); - virtual void ReportError(const char* /*msg*/) {} + virtual void ReportError(const std::string& /*msg*/) {} + + virtual bool setSourceEncoding(const std::string& /*codepage*/) { return true; } + virtual std::string toUtf8(const std::string& strSource) { return strSource; } + +private: + std::string m_CodePage; // Code Page name from $DWGCODEPAGE or null if none/not read yet public: CDxfRead(const char* filepath); // this opens the file virtual ~CDxfRead(); // this closes the file - bool Failed(){return m_fail;} - void DoRead(const bool ignore_errors = false); // this reads the file and calls the following functions + bool Failed() + { + return m_fail; + } + void DoRead( + const bool ignore_errors = false); // this reads the file and calls the following functions double mm( double value ) const; - bool IgnoreErrors() const { return(m_ignore_errors); } - - virtual void OnReadLine(const double* /*s*/, const double* /*e*/, bool /*hidden*/){} - virtual void OnReadPoint(const double* /*s*/){} - virtual void OnReadText(const double* /*point*/, const double /*height*/, double /*rotation*/, const char* /*text*/){} - virtual void OnReadArc(const double* /*s*/, const double* /*e*/, const double* /*c*/, bool /*dir*/, bool /*hidden*/){} - virtual void OnReadCircle(const double* /*s*/, const double* /*c*/, bool /*dir*/, bool /*hidden*/){} - virtual void OnReadEllipse(const double* /*c*/, double /*major_radius*/, double /*minor_radius*/, double /*rotation*/, double /*start_angle*/, double /*end_angle*/, bool /*dir*/){} - virtual void OnReadSpline(struct SplineData& /*sd*/){} - virtual void OnReadInsert(const double* /*point*/, const double* /*scale*/, const char* /*name*/, double /*rotation*/){} - virtual void OnReadDimension(const double* /*s*/, const double* /*e*/, const double* /*point*/, double /*rotation*/){} - virtual void AddGraphics() const { } + bool IgnoreErrors() const + { + return(m_ignore_errors); + } + + virtual void OnReadLine(const double* /*s*/, const double* /*e*/, bool /*hidden*/) + {} + virtual void OnReadPoint(const double* /*s*/) + {} + virtual void OnReadText(const DxfText&) {} + virtual void OnReadArc(const double* /*s*/, + const double* /*e*/, + const double* /*c*/, + bool /*dir*/, + bool /*hidden*/) + {} + virtual void OnReadCircle(const double* /*s*/, const double* /*c*/, bool /*dir*/, bool /*hidden*/) + {} + virtual void OnReadEllipse(const double* /*c*/, + double /*major_radius*/, + double /*minor_radius*/, + double /*rotation*/, + double /*start_angle*/, + double /*end_angle*/, + bool /*dir*/) + {} + virtual void OnReadSpline(struct SplineData& /*sd*/) + {} + virtual void OnReadInsert(const double* /*point*/, + const double* /*scale*/, + const char* /*name*/, + double /*rotation*/) + {} + virtual void OnReadDimension(const double* /*s*/, + const double* /*e*/, + const double* /*point*/, + double /*rotation*/) + {} + virtual void AddGraphics() const + {} std::string LayerName() const; - }; diff --git a/src/io_dxf/io_dxf.cpp b/src/io_dxf/io_dxf.cpp index 1d7b29da..37dc2d73 100644 --- a/src/io_dxf/io_dxf.cpp +++ b/src/io_dxf/io_dxf.cpp @@ -16,6 +16,7 @@ #include "../base/property_enumeration.h" #include "../base/task_progress.h" #include "../base/string_conv.h" +#include "../base/tkernel_utils.h" #include "../base/unit_system.h" #include "aci_table.h" #include "dxf.h" @@ -26,16 +27,20 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -74,9 +79,12 @@ class DxfReader::Internal : public CDxfRead { TaskProgress* m_progress = nullptr; std::uintmax_t m_fileSize = 0; std::uintmax_t m_fileReadSize = 0; + Resource_FormatType m_srcEncoding = Resource_ANSI; protected: void get_line() override; + bool setSourceEncoding(const std::string& codepage) override; + std::string toUtf8(const std::string& strSource) override; public: Internal(const FilePath& filepath, TaskProgress* progress = nullptr); @@ -88,7 +96,7 @@ class DxfReader::Internal : public CDxfRead { // CDxfRead's virtual functions void OnReadLine(const double* s, const double* e, bool hidden) override; void OnReadPoint(const double* s) override; - void OnReadText(const double* point, const double height, double rotation, const char* text) override; + void OnReadText(const DxfText& text) override; void OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden) override; void OnReadCircle(const double* s, const double* c, bool dir, bool hidden) override; void OnReadEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir) override; @@ -96,7 +104,7 @@ class DxfReader::Internal : public CDxfRead { void OnReadInsert(const double* point, const double* scale, const char* name, double rotation) override; void OnReadDimension(const double* s, const double* e, const double* point, double rotation) override; - void ReportError(const char* msg) override; + void ReportError(const std::string& msg) override; static Handle_Geom_BSplineCurve createSplineFromPolesAndKnots(struct SplineData& sd); static Handle_Geom_BSplineCurve createInterpolationSpline(struct SplineData& sd); @@ -153,7 +161,7 @@ TDF_LabelSequence DxfReader::transfer(DocumentPtr doc, TaskProgress* progress) Handle_XCAFDoc_ColorTool colorTool = doc->xcaf().colorTool(); Handle_XCAFDoc_LayerTool layerTool = doc->xcaf().layerTool(); std::unordered_map mapLayerNameLabel; - std::unordered_map mapAciColorLabel; + std::unordered_map mapAciColorLabel; auto fnAddRootShape = [&](const TopoDS_Shape& shape, const std::string& shapeName, TDF_Label layer) { const TDF_Label labelShape = shapeTool->NewShape(); @@ -166,7 +174,7 @@ TDF_LabelSequence DxfReader::transfer(DocumentPtr doc, TaskProgress* progress) return labelShape; }; - auto fnAddAci = [&](Aci_t aci) { + auto fnAddAci = [&](ColorIndex_t aci) { auto it = mapAciColorLabel.find(aci); if (it != mapAciColorLabel.cend()) return it->second; @@ -225,7 +233,7 @@ TDF_LabelSequence DxfReader::transfer(DocumentPtr doc, TaskProgress* progress) const TDF_Label compLabel = fnAddRootShape(comp, layerName, layerLabel); // Check if all entities have the same color bool uniqueColor = true; - const Aci_t aci = !vecEntity.empty() ? vecEntity.front().aci : -1; + const ColorIndex_t aci = !vecEntity.empty() ? vecEntity.front().aci : -1; for (const Entity& entity : vecEntity) { uniqueColor = entity.aci == aci; if (!uniqueColor) @@ -277,6 +285,76 @@ void DxfReader::Internal::get_line() m_progress->setValue(MathUtils::toPercent(m_fileReadSize, 0, m_fileSize)); } +bool DxfReader::Internal::setSourceEncoding(const std::string& codepage) +{ + std::optional encoding; + +#if OCC_VERSION_HEX >= OCC_VERSION_CHECK(7, 4, 0) + if (codepage == "UTF8") + encoding = Resource_FormatType_UTF8; + else if (codepage == "ANSI_932") // Japanese + encoding = Resource_FormatType_SJIS; + else if (codepage == "ANSI_936") // UnifiedChinese + encoding = Resource_FormatType_GB; + else if (codepage == "ANSI_949") // Korean + encoding = Resource_FormatType_EUC; +#endif + +#if OCC_VERSION_HEX >= OCC_VERSION_CHECK(7, 5, 0) + if (encoding) + ; // NOP: encoding already found above + else if (codepage == "ANSI_936") // UnifiedChinese + encoding = Resource_FormatType_GBK; + else if (codepage == "ANSI_950") // TradChinese + encoding = Resource_FormatType_Big5; + else if (codepage == "ANSI_1250") + encoding = Resource_FormatType_CP1250; + else if (codepage == "ANSI_1251") + encoding = Resource_FormatType_CP1251; + else if (codepage == "ANSI_1252") + encoding = Resource_FormatType_CP1252; + else if (codepage == "ANSI_1253") + encoding = Resource_FormatType_CP1253; + else if (codepage == "ANSI_1254") + encoding = Resource_FormatType_CP1254; + else if (codepage == "ANSI_1255") + encoding = Resource_FormatType_CP1255; + else if (codepage == "ANSI_1256") + encoding = Resource_FormatType_CP1256; + else if (codepage == "ANSI_1257") + encoding = Resource_FormatType_CP1257; + else if (codepage == "ANSI_1258") + encoding = Resource_FormatType_CP1258; +#endif + + if (encoding) { + m_srcEncoding = encoding.value(); + } + else { + m_srcEncoding = Resource_ANSI; + m_messenger->emitWarning("Codepage " + codepage + " not supported"); + } + + return true; +} + +std::string DxfReader::Internal::toUtf8(const std::string& strSource) +{ + if (m_srcEncoding == Resource_ANSI) // Resource_ANSI is a pass-through(OpenCascade) + return strSource; + +#if OCC_VERSION_HEX >= OCC_VERSION_CHECK(7, 4, 0) + if (m_srcEncoding == Resource_FormatType_UTF8) + return strSource; + + TCollection_ExtendedString extStr; + Resource_Unicode::ConvertFormatToUnicode(m_srcEncoding, strSource.c_str(), extStr); + return to_stdString(extStr); +#else + return strSource; +#endif +} + DxfReader::Internal::Internal(const FilePath& filepath, TaskProgress* progress) : CDxfRead(filepath.u8string().c_str()), m_progress(progress) @@ -302,25 +380,40 @@ void DxfReader::Internal::OnReadPoint(const double* s) this->addShape(vertex); } -void DxfReader::Internal::OnReadText(const double* point, const double height, double rotation, const char* text) +void DxfReader::Internal::OnReadText(const DxfText& text) { if (!m_params.importAnnotations) return; - const gp_Pnt pt = this->toPnt(point); + const gp_Pnt pt = this->toPnt(text.point); const std::string layerName = this->LayerName(); if (!startsWith(layerName, "BLOCKS")) { const std::string& fontName = m_params.fontNameForTextObjects; - const double fontHeight = 4 * height * m_params.scaling; + const double fontHeight = 4 * text.height * m_params.scaling; Font_BRepFont brepFont; if (brepFont.Init(fontName.c_str(), Font_FA_Regular, fontHeight)) { gp_Trsf rotTrsf; - if (rotation != 0.) - rotTrsf.SetRotation(gp_Ax1(pt, gp::DZ()), UnitSystem::radians(rotation * Quantity_Degree)); + if (!MathUtils::fuzzyIsNull(text.rotation)) + rotTrsf.SetRotation(gp_Ax1(pt, gp::DZ()), text.rotation); + + const int ap = static_cast(text.attachPoint); + Graphic3d_HorizontalTextAlignment hAttachPnt = Graphic3d_HTA_LEFT; + if (ap == 2 || ap == 5 || ap == 8) + hAttachPnt = Graphic3d_HTA_CENTER; + else if (ap == 3 || ap == 6 || ap == 9) + hAttachPnt = Graphic3d_HTA_RIGHT; + + Graphic3d_VerticalTextAlignment vAttachPnt = Graphic3d_VTA_TOP; + if (ap == 4 || ap == 5 || ap == 6) + vAttachPnt = Graphic3d_VTA_CENTER; + else if (ap == 7 || ap == 8 || ap == 9) + vAttachPnt = Graphic3d_VTA_BOTTOM; const gp_Ax3 locText(pt, gp::DZ(), gp::DX().Transformed(rotTrsf)); Font_BRepTextBuilder brepTextBuilder; - const TopoDS_Shape shapeText = brepTextBuilder.Perform(brepFont, text, locText); + const TopoDS_Shape shapeText = brepTextBuilder.Perform( + brepFont, string_conv(text.str), locText, hAttachPnt, vAttachPnt + ); this->addShape(shapeText); } else { @@ -368,7 +461,8 @@ void DxfReader::Internal::OnReadEllipse( double major_radius, double minor_radius, double rotation, double /*start_angle*/, double /*end_angle*/, - bool dir) + bool dir + ) { const gp_Dir up = dir ? gp::DZ() : -gp::DZ(); const gp_Pnt pc = this->toPnt(c); @@ -435,7 +529,8 @@ void DxfReader::Internal::OnReadInsert(const double* point, const double* scale, trsfScale.SetValues( nscale[0], 0, 0, 0, 0, nscale[1], 0, 0, - 0, 0, nscale[2], 0); + 0, 0, nscale[2], 0 + ); gp_Trsf trsfRotZ; trsfRotZ.SetRotation(gp::OZ(), rotation); gp_Trsf trsfMove; @@ -460,7 +555,7 @@ void DxfReader::Internal::OnReadDimension(const double* s, const double* e, cons } } -void DxfReader::Internal::ReportError(const char* msg) +void DxfReader::Internal::ReportError(const std::string& msg) { m_messenger->emitError(msg); } @@ -481,7 +576,7 @@ gp_Pnt DxfReader::Internal::toPnt(const double* coords) const void DxfReader::Internal::addShape(const TopoDS_Shape& shape) { - const Entity newEntity{ m_aci, shape }; + const Entity newEntity{ m_ColorIndex, shape }; const std::string layerName = this->LayerName(); auto itFound = m_layers.find(layerName); if (itFound != m_layers.end()) { diff --git a/src/io_off/io_off_reader.h b/src/io_off/io_off_reader.h index eba56187..c5e319f9 100644 --- a/src/io_off/io_off_reader.h +++ b/src/io_off/io_off_reader.h @@ -11,7 +11,6 @@ #include #include - #include namespace Mayo {