/****************************************************************************** ** libDXFrw - Library to read/write DXF files (ascii & binary) ** ** ** ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** ** ** ** This library is free software, licensed under the terms of the GNU ** ** General Public License as published by the Free Software Foundation, ** ** either version 2 of the License, or (at your option) any later version. ** ** You should have received a copy of the GNU General Public License ** ** along with this program. If not, see . ** ******************************************************************************/ #ifndef DRW_BASE_H #define DRW_BASE_H #define DRW_VERSION "0.6.3" #include #include #include #include #include // Header is removed in C++20. #if __cplusplus <= 201703L #include // and, not, or #endif #ifdef DRW_ASSERTS #define drw_assert(a) assert(a) #else #define drw_assert(a) #endif #define UTF8STRING std::string #define DRW_UNUSED(x) (void)x #if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) #define DRW_WIN #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) #define DRW_WIN #elif defined(__MWERKS__) && defined(__INTEL__) #define DRW_WIN #else #define DRW_POSIX #endif #ifndef M_PI #define M_PI 3.141592653589793238462643 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #define M_PIx2 6.283185307179586 // 2*PI #define ARAD 57.29577951308232 #ifndef __has_cpp_attribute #define __has_cpp_attribute(x) 0 #endif #ifndef Q_DISABLE_ASSIGN_MOVE #define Q_DISABLE_ASSIGN_MOVE(Class) \ Q_DISABLE_ASSIGN(Class) \ Class(Class &&) = delete; \ Class &operator=(Class &&) = delete; #endif using dint8 = signed char; /* 8 bit signed */ using dint16 = short; /* 16 bit signed */ using dint32 = int; /* 32 bit signed */ using dint64 = long long; /* 64 bit signed */ using duint8 = unsigned char; /* 8 bit unsigned */ using duint16 = unsigned short; /* 16 bit unsigned */ using duint32 = unsigned int; /* 32 bit unsigned */ using duint64 = unsigned long long; /* 64 bit unsigned */ using dfloat32 = float; /* 32 bit floating point */ using ddouble64 = double; /* 64 bit floating point */ using ddouble80 = long double; /* 80 bit floating point */ namespace DRW { //! Version numbers for the DXF Format. enum Version { UNKNOWNV, //!< UNKNOWN VERSION. MC00, //!< DWG Release 1.1 AC12, //!< DWG Release 1.2 AC14, //!< DWG Release 1.4 AC150, //!< DWG Release 2.0 AC210, //!< DWG Release 2.10 AC1002, //!< DWG Release 2.5 AC1003, //!< DWG Release 2.6 AC1004, //!< DWG Relase 9 AC1006, //!< DWG Release 10 (R10) AC1009, //!< DWG Release 11/12 (LT R1/R2) (R11 & R12) AC1012, //!< DWG Release 13 (LT95) (R13) AC1014, //!< DWG Release 14/14.01 (LT97/LT98) (R14) AC1015, //!< AutoCAD 2000/2000i/2002 (ACAD 2000) AC1018, //!< AutoCAD 2004/2005/2006 (ACAD 2004) AC1021, //!< AutoCAD 2007/2008/2009 (ACAD 2007) AC1024, //!< AutoCAD 2010/2011/2012 (ACAD 2010) AC1027, //!< AutoCAD 2013/2014/2015/2016/2017 (ACAD 2013) AC1032, //!< AutoCAD 2018/2019/2020 (ACAD 2018) }; const std::unordered_map dwgVersionStrings{ {"MC0.0", DRW::MC00}, {"AC1.2", DRW::AC12}, {"AC1.4", DRW::AC14}, {"AC1.50", DRW::AC150}, {"AC2.10", DRW::AC210}, {"AC1002", DRW::AC1002}, {"AC1003", DRW::AC1003}, {"AC1004", DRW::AC1004}, {"AC1006", DRW::AC1006}, {"AC1009", DRW::AC1009}, {"AC1012", DRW::AC1012}, {"AC1014", DRW::AC1014}, {"AC1015", DRW::AC1015}, {"AC1018", DRW::AC1018}, {"AC1021", DRW::AC1021}, {"AC1024", DRW::AC1024}, {"AC1027", DRW::AC1027}, {"AC1032", DRW::AC1032}, }; enum error { BAD_NONE, /*!< No error. */ BAD_UNKNOWN, /*!< UNKNOWN. */ BAD_OPEN, /*!< error opening file. */ BAD_VERSION, /*!< unsupported version. */ BAD_READ_METADATA, /*!< error reading matadata. */ BAD_READ_FILE_HEADER, /*!< error in file header read process. */ BAD_READ_HEADER, /*!< error in header vars read process. */ BAD_READ_HANDLES, /*!< error in object map read process. */ BAD_READ_CLASSES, /*!< error in classes read process. */ BAD_READ_TABLES, /*!< error in tables read process. */ BAD_READ_BLOCKS, /*!< error in block read process. */ BAD_READ_ENTITIES, /*!< error in entities read process. */ BAD_READ_OBJECTS, /*!< error in objects read process. */ BAD_READ_SECTION, /*!< error in sections read process. */ BAD_CODE_PARSED, /*!< error in any parseCodes() method. */ }; enum class DebugLevel { None, Debug }; /** * Interface for debug printers. * * The base class is silent and ignores all debugging. */ class DebugPrinter { public: virtual void printS(const std::string &s) { (void)s; } virtual void printI(long long int i) { (void)i; } virtual void printUI(long long unsigned int i) { (void)i; } virtual void printD(double d) { (void)d; } virtual void printH(long long int i) { (void)i; } virtual void printB(int i) { (void)i; } virtual void printHL(int c, int s, int h) { (void)c; (void)s; (void)h; } virtual void printPT(double x, double y, double z) { (void)x; (void)y; (void)z; } DebugPrinter() = default; virtual ~DebugPrinter() = default; }; /** * Sets a custom debug printer to use when outputting debug messages. * * Ownership of `printer` is transferred. */ void setCustomDebugPrinter(DebugPrinter *printer); //! Special codes for colors enum ColorCodes { black = 250, green = 3, red = 1, brown = 15, yellow = 2, cyan = 4, magenta = 6, gray = 8, blue = 5, l_blue = 163, l_green = 121, l_cyan = 131, l_red = 23, l_magenta = 221, l_gray = 252, white = 7, ColorByLayer = 256, ColorByBlock = 0 }; //! Spaces enum Space { ModelSpace = 0, PaperSpace = 1 }; //! Special kinds of handles enum HandleCodes { NoHandle = 0 }; //! Shadow mode enum ShadowMode { CastAndReceieveShadows = 0, CastShadows = 1, ReceiveShadows = 2, IgnoreShadows = 3 }; //! Special kinds of materials enum MaterialCodes { MaterialByLayer = 0 }; //! Special kinds of plot styles enum PlotStyleCodes { DefaultPlotStyle = 0 }; //! Special kinds of transparencies enum TransparencyCodes { Opaque = 0, Transparent = -1 }; } // namespace DRW Q_REQUIRED_RESULT static inline auto DRW_FuzzyComparePossibleNulls(double p1, double p2) -> bool; static inline auto DRW_FuzzyComparePossibleNulls(double p1, double p2) -> bool { if (qFuzzyIsNull(p1)) { return qFuzzyIsNull(p2); } if (qFuzzyIsNull(p2)) { return false; } return qFuzzyCompare(p1, p2); } //! Class to handle 3D coordinate point /*! * Class to handle 3D coordinate point * @author Rallaz */ class DRW_Coord { public: DRW_Coord() = default; DRW_Coord(double ix, double iy, double iz) : x(ix), y(iy), z(iz) { } DRW_Coord(const DRW_Coord &data) : x(data.x), y(data.y), z(data.z) { } auto operator=(const DRW_Coord &data) -> DRW_Coord & { if (&data == this) { return *this; } x = data.x; y = data.y; z = data.z; return *this; } /*!< convert to unitary vector */ void unitize() { double dist; dist = hypot(hypot(x, y), z); if (dist > 0.0) { x = x / dist; y = y / dist; z = z / dist; } } public: double x{0}; double y{0}; double z{0}; }; //! Class to handle vertex /*! * Class to handle vertex for lwpolyline entity * @author Rallaz */ class DRW_Vertex2D { public: DRW_Vertex2D() : x(), y(), stawidth(0), endwidth(0), bulge(0) { // eType = DRW::LWPOLYLINE; } DRW_Vertex2D(double sx, double sy, double b = 0.0) : x(sx), y(sy), stawidth(0), endwidth(0), bulge(b) { } public: double x; /*!< x coordinate, code 10 */ double y; /*!< y coordinate, code 20 */ double stawidth; /*!< Start width, code 40 */ double endwidth; /*!< End width, code 41 */ double bulge; /*!< bulge, code 42 */ }; //! Class to handle header vars /*! * Class to handle header vars * @author Rallaz */ class DRW_Variant { public: enum TYPE { STRING, INTEGER, DOUBLE, COORD, INVALID }; // TODO: add INT64 support DRW_Variant() : content(), type(INVALID), code(), sdata(), vdata() { } DRW_Variant(int c, dint32 i) : content(), type(), code(c), sdata(), vdata() { addInt(i); } DRW_Variant(int c, duint32 i) : content(), type(), code(c), sdata(), vdata() { addInt(static_cast(i)); // RLZ: verify if work with big numbers } DRW_Variant(int c, double d) : content(), type(), code(c), sdata(), vdata() { addDouble(d); } DRW_Variant(int c, const UTF8STRING &s) : content(), type(), code(c), sdata(), vdata() { addString(s); } DRW_Variant(int c, const DRW_Coord &crd) : content(), type(), code(c), sdata(), vdata() { addCoord(crd); } DRW_Variant(const DRW_Variant &d) : content(d.content), type(d.type), code(d.code), sdata(), vdata() { if (d.type == COORD) { vdata = d.vdata; content.v = &vdata; } if (d.type == STRING) { sdata = d.sdata; content.s = &sdata; } } ~DRW_Variant() = default; void addString(const UTF8STRING &s) { setType(STRING); sdata = s; content.s = &sdata; } void addInt(int i) { setType(INTEGER); content.i = i; } void addDouble(double d) { setType(DOUBLE); content.d = d; } void addCoord() { setType(COORD); vdata.x = 0.0; vdata.y = 0.0; vdata.z = 0.0; content.v = &vdata; } void addCoord(const DRW_Coord &v) { setType(COORD); vdata = v; content.v = &vdata; } void setType(TYPE t) { type = t; } void setCoordX(double d) { if (type == COORD) vdata.x = d; } void setCoordY(double d) { if (type == COORD) vdata.y = d; } void setCoordZ(double d) { if (type == COORD) vdata.z = d; } private: using DRW_VarContent = union { UTF8STRING *s; dint32 i; double d; DRW_Coord *v; }; public: DRW_VarContent content; TYPE type; int code; /*!< dxf code of this value*/ private: auto operator=(const DRW_Variant &) -> DRW_Variant &Q_DECL_EQ_DELETE; std::string sdata; DRW_Coord vdata; }; //! Class to convert between line width and integer /*! * Class to convert between line width and integer * verifing valid values, if value is not valid * returns widthDefault. * @author Rallaz */ class DRW_LW_Conv { public: enum lineWidth { width00 = 0, /*!< 0.00mm (dxf 0)*/ width01 = 1, /*!< 0.05mm (dxf 5)*/ width02 = 2, /*!< 0.09mm (dxf 9)*/ width03 = 3, /*!< 0.13mm (dxf 13)*/ width04 = 4, /*!< 0.15mm (dxf 15)*/ width05 = 5, /*!< 0.18mm (dxf 18)*/ width06 = 6, /*!< 0.20mm (dxf 20)*/ width07 = 7, /*!< 0.25mm (dxf 25)*/ width08 = 8, /*!< 0.30mm (dxf 30)*/ width09 = 9, /*!< 0.35mm (dxf 35)*/ width10 = 10, /*!< 0.40mm (dxf 40)*/ width11 = 11, /*!< 0.50mm (dxf 50)*/ width12 = 12, /*!< 0.53mm (dxf 53)*/ width13 = 13, /*!< 0.60mm (dxf 60)*/ width14 = 14, /*!< 0.70mm (dxf 70)*/ width15 = 15, /*!< 0.80mm (dxf 80)*/ width16 = 16, /*!< 0.90mm (dxf 90)*/ width17 = 17, /*!< 1.00mm (dxf 100)*/ width18 = 18, /*!< 1.06mm (dxf 106)*/ width19 = 19, /*!< 1.20mm (dxf 120)*/ width20 = 20, /*!< 1.40mm (dxf 140)*/ width21 = 21, /*!< 1.58mm (dxf 158)*/ width22 = 22, /*!< 2.00mm (dxf 200)*/ width23 = 23, /*!< 2.11mm (dxf 211)*/ widthByLayer = 29, /*!< by layer (dxf -1) */ widthByBlock = 30, /*!< by block (dxf -2) */ widthDefault = 31 /*!< by default (dxf -3) */ }; static auto lineWidth2dxfInt(lineWidth lw) -> int { switch (lw) { case widthByLayer: return -1; case widthByBlock: return -2; case widthDefault: return -3; case width00: return 0; case width01: return 5; case width02: return 9; case width03: return 13; case width04: return 15; case width05: return 18; case width06: return 20; case width07: return 25; case width08: return 30; case width09: return 35; case width10: return 40; case width11: return 50; case width12: return 53; case width13: return 60; case width14: return 70; case width15: return 80; case width16: return 90; case width17: return 100; case width18: return 106; case width19: return 120; case width20: return 140; case width21: return 158; case width22: return 200; case width23: return 211; default: break; } return -3; } static auto dxfInt2lineWidth(int i) -> lineWidth { if (i < 0) { if (i == -1) return widthByLayer; if (i == -2) return widthByBlock; else if (i == -3) return widthDefault; } else if (i < 3) { return width00; } else if (i < 7) { return width01; } else if (i < 11) { return width02; } else if (i < 14) { return width03; } else if (i < 16) { return width04; } else if (i < 19) { return width05; } else if (i < 22) { return width06; } else if (i < 27) { return width07; } else if (i < 32) { return width08; } else if (i < 37) { return width09; } else if (i < 45) { return width10; } else if (i < 52) { return width11; } else if (i < 57) { return width12; } else if (i < 65) { return width13; } else if (i < 75) { return width14; } else if (i < 85) { return width15; } else if (i < 95) { return width16; } else if (i < 103) { return width17; } else if (i < 112) { return width18; } else if (i < 130) { return width19; } else if (i < 149) { return width20; } else if (i < 180) { return width21; } else if (i < 205) { return width22; } else { return width23; } // default by default return widthDefault; } }; #endif // EOF