/* Copyright 2006-2026 The QElectroTech Team This file is part of QElectroTech. QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ #include "createdxf.h" #include #include #include #include #include "dxfexport.h" #include #include const double Createdxf::sheetWidth = 4000; const double Createdxf::sheetHeight = 2700; double Createdxf::xScale = 1; namespace { /// @p text on one line. A DXF value ends at the line break, so a break /// inside a text would shift every group code after it by one line and /// a reader would take values for codes (FINDINGS F052). Callers that /// mean several lines split them first; this is the safety net. QString singleLine(QString text) { text.replace(QLatin1String("\r\n"), QLatin1String(" ")); text.replace(QLatin1Char('\r'), QLatin1Char(' ')); text.replace(QLatin1Char('\n'), QLatin1Char(' ')); return text; } /// Colour code of an entity. 0 is BYBLOCK, which means nothing outside a /// block and so fell back to the default colour; it is also what black /// maps to (RGBcodeTable[0]). BYLAYER (256) looks the same, the layers /// being colour 7, and lets a CAD user recolour a whole layer at once /// (discussion #1071). Real colours are kept. int entityColour(int colour) { return colour == 0 ? 256 : colour; } } double Createdxf::yScale = 1; QString Createdxf::layer = QStringLiteral("0"); Createdxf::Createdxf() { } Createdxf::~Createdxf() { } /* Header section of every DXF file. @param layers : the layers the entities will be written on, declared in the LAYER table beside layer "0", which every DXF has. */ void Createdxf::dxfBegin (const QString& fileName, const QStringList &layers) { layer = QStringLiteral("0"); // Creation of an output stream object in text mode. // Header section of every dxf file. if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::WriteOnly)) { // error message QMessageBox errorFileOpen; errorFileOpen.setIcon(QMessageBox::Warning); errorFileOpen.setText("Error: "+fileName+" Could Not be Opened."); errorFileOpen.setInformativeText("Close all Files and Try Again."); errorFileOpen.exec(); exit(0); } else { QTextStream To_Dxf(&file); To_Dxf << 999 << "\r\n"; To_Dxf << "QET" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "SECTION" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "HEADER" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$ACADVER" << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << "AC1006" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$INSBASE" << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 30 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$EXTMIN" << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$EXTMAX" << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << "4000.0" << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << "4000.0" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$LIMMIN" << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << "0.0" << "\r\n"; To_Dxf << 9 << "\r\n"; To_Dxf << "$LIMMAX" << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << "4000.0" << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << "4000.0" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDSEC" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "SECTION" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "TABLES" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "TABLE" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "VPORT" << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "VPORT" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "*ACTIVE" << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 11 << "\r\n"; To_Dxf << 1.0 << "\r\n"; To_Dxf << 21 << "\r\n"; To_Dxf << 1.0 << "\r\n"; To_Dxf << 12 << "\r\n"; To_Dxf << 2000 << "\r\n"; To_Dxf << 22 << "\r\n"; To_Dxf << 1350 << "\r\n"; To_Dxf << 13 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 23 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 14 << "\r\n"; To_Dxf << 1.0 << "\r\n"; To_Dxf << 24 << "\r\n"; To_Dxf << 1.0 << "\r\n"; To_Dxf << 15 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 25 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 16 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 26 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 36 << "\r\n"; To_Dxf << 1.0 << "\r\n"; To_Dxf << 17 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 27 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 37 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 40 << "\r\n"; To_Dxf << 2732.5 << "\r\n"; To_Dxf << 41 << "\r\n"; To_Dxf << 2.558 << "\r\n"; To_Dxf << 42 << "\r\n"; To_Dxf << 50.0 << "\r\n"; To_Dxf << 43 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 44 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 50 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 51 << "\r\n"; To_Dxf << 0.0 << "\r\n"; To_Dxf << 71 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 72 << "\r\n"; To_Dxf << 100 << "\r\n"; To_Dxf << 73 << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << 74 << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << 75 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 76 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 77 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 78 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDTAB" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "TABLE" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "LTYPE" << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "LTYPE" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "CONTINUOUS" << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 64 << "\r\n"; To_Dxf << 3 << "\r\n"; To_Dxf << "Solid Line" << "\r\n"; To_Dxf << 72 << "\r\n"; To_Dxf << 65 << "\r\n"; To_Dxf << 73 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 40 << "\r\n"; To_Dxf << 0.00 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDTAB" << "\r\n"; // Layers: "0" plus the ones the entities use, all white/black // (colour 7) and continuous, so a file looks the same as before // until the user changes a layer. QStringList all_layers{QStringLiteral("0")}; for (const QString &name : layers) { if (!all_layers.contains(name)) all_layers << name; } To_Dxf << 0 << "\r\n"; To_Dxf << "TABLE" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "LAYER" << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << all_layers.size() << "\r\n"; for (const QString &name : std::as_const(all_layers)) { To_Dxf << 0 << "\r\n"; To_Dxf << "LAYER" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << name << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 62 << "\r\n"; To_Dxf << 7 << "\r\n"; To_Dxf << 6 << "\r\n"; To_Dxf << "CONTINUOUS" << "\r\n"; } To_Dxf << 0 << "\r\n"; To_Dxf << "ENDTAB" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDSEC" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "SECTION" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "BLOCKS" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDSEC" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "SECTION" << "\r\n"; To_Dxf << 2 << "\r\n"; To_Dxf << "ENTITIES" << "\r\n"; file.close(); } } } /** @brief Createdxf::dxfEnd End Section of every DXF File @param fileName */ void Createdxf::dxfEnd(const QString& fileName) { layer = QStringLiteral("0"); // Creation of an output stream object in text mode. if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); To_Dxf << 0 << "\r\n"; To_Dxf << "ENDSEC" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "EOF"; file.close(); } } } /** @brief Createdxf::drawCircle draw circle in dxf format @param fileName @param radius @param x @param y @param colour */ void Createdxf::drawCircle( const QString& fileName, double radius, double x, double y, int colour) { if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the circle To_Dxf << 0 << "\r\n"; To_Dxf << "CIRCLE" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(colour) << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ is the Center point of circle To_Dxf << x << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates To_Dxf << 40 << "\r\n"; To_Dxf << radius << "\r\n"; // radius of circle file.close(); } } } /** @brief Createdxf::drawLine draw line in DXF Format @param fileName @param x1 @param y1 @param x2 @param y2 @param colour */ void Createdxf::drawLine ( const QString &fileName, double x1, double y1, double x2, double y2, const int &colour) { if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the Line To_Dxf << 0 << "\r\n"; To_Dxf << "LINE" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(colour) << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; To_Dxf << x1 << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y1 << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates To_Dxf << 11 << "\r\n"; To_Dxf << x2 << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 21 << "\r\n"; To_Dxf << y2 << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 31 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates file.close(); } } } long Createdxf::RGBcodeTable[255] { 0x000000, 0xff0000, 0xffff00, 0x00ff00, 0x00ffff, 0x0000ff, 0xff00ff, 0xffffff, 0x414141, 0x808080, 0xff0000, 0xffaaaa, 0xbd0000, 0xbd7e7e, 0x810000, 0x815656, 0x680000, 0x684545, 0x4f0000, 0x4f3535, 0xff3f00, 0xffbfaa, 0xbd2e00, 0xbd8d7e, 0x811f00, 0x816056, 0x681900, 0x684e45, 0x4f1300, 0x4f3b35, 0xff7f00, 0xffd4aa, 0xbd5e00, 0xbd9d7e, 0x814000, 0x816b56, 0x683400, 0x685645, 0x4f2700, 0x4f4235, 0xffbf00, 0xffeaaa, 0xbd8d00, 0xbdad7e, 0x816000, 0x817656, 0x684e00, 0x685f45, 0x4f3b00, 0x4f4935, 0xffff00, 0xffffaa, 0xbdbd00, 0xbdbd7e, 0x818100, 0x818156, 0x686800, 0x686845, 0x4f4f00, 0x4f4f35, 0xbfff00, 0xeaffaa, 0x8dbd00, 0xadbd7e, 0x608100, 0x768156, 0x4e6800, 0x5f6845, 0x3b4f00, 0x494f35, 0x7fff00, 0xd4ffaa, 0x5ebd00, 0x9dbd7e, 0x408100, 0x6b8156, 0x346800, 0x566845, 0x274f00, 0x424f35, 0x3fff00, 0xbfffaa, 0x2ebd00, 0x8dbd7e, 0x1f8100, 0x608156, 0x196800, 0x4e6845, 0x134f00, 0x3b4f35, 0x00ff00, 0xaaffaa, 0x00bd00, 0x7ebd7e, 0x008100, 0x568156, 0x006800, 0x456845, 0x004f00, 0x354f35, 0x00ff3f, 0xaaffbf, 0x00bd2e, 0x7ebd8d, 0x00811f, 0x568160, 0x006819, 0x45684e, 0x004f13, 0x354f3b, 0x00ff7f, 0xaaffd4, 0x00bd5e, 0x7ebd9d, 0x008140, 0x56816b, 0x006834, 0x456856, 0x004f27, 0x354f42, 0x00ffbf, 0xaaffea, 0x00bd8d, 0x7ebdad, 0x008160, 0x568176, 0x00684e, 0x45685f, 0x004f3b, 0x354f49, 0x00ffff, 0xaaffff, 0x00bdbd, 0x7ebdbd, 0x008181, 0x568181, 0x006868, 0x456868, 0x004f4f, 0x354f4f, 0x00bfff, 0xaaeaff, 0x008dbd, 0x7eadbd, 0x006081, 0x567681, 0x004e68, 0x455f68, 0x003b4f, 0x35494f, 0x007fff, 0xaad4ff, 0x005ebd, 0x7e9dbd, 0x004081, 0x566b81, 0x003468, 0x455668, 0x00274f, 0x35424f, 0x003fff, 0xaabfff, 0x002ebd, 0x7e8dbd, 0x001f81, 0x566081, 0x001968, 0x454e68, 0x00134f, 0x353b4f, 0x0000ff, 0xaaaaff, 0x0000bd, 0x7e7ebd, 0x000081, 0x565681, 0x000068, 0x454568, 0x00004f, 0x35354f, 0x3f00ff, 0xbfaaff, 0x2e00bd, 0x8d7ebd, 0x1f0081, 0x605681, 0x190068, 0x4e4568, 0x13004f, 0x3b354f, 0x7f00ff, 0xd4aaff, 0x5e00bd, 0x9d7ebd, 0x400081, 0x6b5681, 0x340068, 0x564568, 0x27004f, 0x42354f, 0xbf00ff, 0xeeaaff, 0x8d00bd, 0xad7ebd, 0x600081, 0x765681, 0x4e0068, 0x5f4568, 0x3b004f, 0x49354f, 0xff00ff, 0xffaaff, 0xbd00bd, 0xbd7ebd, 0x810081, 0x815681, 0x680068, 0x684568, 0x4f004f, 0x4f354f, 0xff00bf, 0xffaaea, 0xbd008d, 0xbd7ead, 0x810060, 0x815676, 0x68004e, 0x68455f, 0x4f003b, 0x4f3549, 0xff007f, 0xffaad4, 0xbd005e, 0xbd7e9d, 0x810040, 0x81566b, 0x680034, 0x684556, 0x4f0027, 0x4f3542, 0xff003f, 0xffaabf, 0xbd002e, 0xbd7e8d, 0x81001f, 0x815660, 0x680019, 0x68454e, 0x4f0013, 0x4f353b, 0x333333, 0x505050, 0x696969, 0x828282, 0xbebebe }; /** @brief Createdxf::getcolorCode This function returns the ACI color which is the "nearest" color to the color defined by the red, green and blue (RGB) values passed in argument. @param red @param green @param blue */ int Createdxf::getcolorCode (const long red, const long green, const long blue) { long acirgb, r,g,b; long mindst = 2147483647L; long dst = 0; int minndx = 0; for ( int i = 0; i < 254; i++ ) { acirgb = RGBcodeTable[i]; b = ( acirgb & 0xffL ); g = ( acirgb & 0xff00L ) >> 8; r = acirgb >> 16; dst = abs ( r-red) + abs ( g -green) + abs (b-blue); if ( dst < mindst ) { minndx = i; mindst = dst; } } return minndx; } int Createdxf::dxfColor(QColor color) { return Createdxf::getcolorCode(color.red(), color.green(), color.blue()); } int Createdxf::dxfColor(QPen pen) { return Createdxf::dxfColor(pen.color()); } /** @brief Createdxf::drawArcEllipse Draw an arc of an ellipse, or a whole ellipse, in DXF units. @param x, y : top left of the ellipse's bounding rect (y is the top, the DXF Y axis going up) @param w, h : width and height of that rect @param startAngle, spanAngle : in degrees, as QPainter::drawArc() takes them: counter-clockwise from 3 o'clock @param hotspot_x, hotspot_y, rotation_angle : the whole shape is turned clockwise by rotation_angle degrees around the hotspot, as a rotated symbol is A circle, or an arc of one, is written as one exact CIRCLE or ARC. R10, the version this file declares, has no ELLIPSE entity, so a true ellipse is written as a polyline through points of the curve, one every 5 degrees. It used to be four ARCs fitted through a point between the curve and its chord, which drew every circle as a flattened diamond (issue #1339). */ void Createdxf::drawArcEllipse( const QString &file_path, qreal x, qreal y, qreal w, qreal h, qreal startAngle, qreal spanAngle, qreal hotspot_x, qreal hotspot_y, qreal rotation_angle, const int &colorcode) { if (qFuzzyIsNull(spanAngle) || w <= 0 || h <= 0) return; const qreal a = w/2; const qreal b = h/2; const QPointF center = DxfExport::rotation_transformed( x + a, y - b, hotspot_x, hotspot_y, rotation_angle); const bool full_turn = qAbs(spanAngle) >= 360; if (qAbs(a - b) <= 1e-6 * qMax(a, b)) { if (full_turn) { drawCircle(file_path, a, center.x(), center.y(), colorcode); return; } //A DXF ARC always runs counter-clockwise from 50 to 51. qreal start = startAngle - rotation_angle; if (spanAngle < 0) start += spanAngle; start = std::fmod(start, 360.0); if (start < 0) start += 360; drawArc(file_path, center.x(), center.y(), a, start, start + qAbs(spanAngle), colorcode); return; } const qreal span = full_turn ? 360 : spanAngle; const int steps = qMax(2, qCeil(qAbs(span) / 5)); QPolygonF poly; poly.reserve(steps + 1); for (int i = 0 ; i <= steps ; ++i) { const qreal theta = qDegreesToRadians(startAngle + span * i / steps); poly << DxfExport::rotation_transformed( x + a + a*std::cos(theta), y - b + b*std::sin(theta), hotspot_x, hotspot_y, rotation_angle); } drawPolyline(file_path, poly, colorcode, true); } /** @brief Createdxf::drawRectangle draw rectangle in dxf format @param fileName @param x1 @param y1 @param width @param height @param colour */ void Createdxf::drawRectangle ( const QString &fileName, double x1, double y1, double width, double height, const int &colour) { QRectF rect(x1,y1,width,height); QPolygonF poly(rect); drawPolyline(fileName,poly,colour,true); } /** @brief Createdxf::drawArc draw arc in dx format @param fileName @param x @param y @param rad @param startAngle @param endAngle @param color */ void Createdxf::drawArc( const QString& fileName, double x, double y, double rad, double startAngle, double endAngle, int color) { if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the arc To_Dxf << 0 << "\r\n"; To_Dxf << "ARC" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(color) << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ is the Center point of circle To_Dxf << x << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates To_Dxf << 40 << "\r\n"; To_Dxf << rad << "\r\n"; // radius of arc To_Dxf << 50 << "\r\n"; To_Dxf << startAngle<< "\r\n"; // start angle To_Dxf << 51 << "\r\n"; To_Dxf << endAngle << "\r\n"; // end angle file.close(); } } } /** @brief Createdxf::drawText draw simple text in dxf format without any alignment specified @param fileName @param text @param x @param y @param height @param rotation @param colour @param xScaleW = 1 */ void Createdxf::drawText( const QString& fileName, const QString& text, double x, double y, double height, double rotation, int colour, double xScaleW) { if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the text To_Dxf << 0 << "\r\n"; To_Dxf << "TEXT" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(colour) << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ To_Dxf << x << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates To_Dxf << 40 << "\r\n"; To_Dxf << height << "\r\n"; // Text Height To_Dxf << 41 << "\r\n"; To_Dxf << xScaleW << "\r\n"; // X Scale To_Dxf << 1 << "\r\n"; To_Dxf << singleLine(text) << "\r\n"; // Text Value To_Dxf << 50 << "\r\n"; To_Dxf << rotation << "\r\n"; // Text Rotation file.close(); } } } /* draw aligned text in DXF Format */ // leftAlign flag added. If the alignment requested is 'fit to width' and the text length is very small, // then the text is either centered or left-aligned, depnding on the value of leftAlign. void Createdxf::drawTextAligned( const QString& fileName, const QString& text, double x, double y, double height, double rotation, double oblique, int hAlign, int vAlign, double xAlign, double xScaleW, int colour) { drawTextAligned(fileName, text, x, y, height, rotation, oblique, hAlign, vAlign, xAlign, y, xScaleW, colour); } /** @brief Createdxf::drawTextAligned As above, with the second alignment point given in full (@a xAlign, @a yAlign) instead of on the same horizontal line as the insertion point, which is what a rotated aligned text needs. */ void Createdxf::drawTextAligned( const QString& fileName, const QString& text, double x, double y, double height, double rotation, double oblique, int hAlign, int vAlign, double xAlign, double yAlign, double xScaleW, int colour) { if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+fileName+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the circle To_Dxf << 0 << "\r\n"; To_Dxf << "TEXT" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(colour) << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ To_Dxf << x << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates To_Dxf << 40 << "\r\n"; To_Dxf << height << "\r\n"; // Text Height To_Dxf << 41 << "\r\n"; To_Dxf << xScaleW << "\r\n"; // X Scale To_Dxf << 1 << "\r\n"; To_Dxf << singleLine(text) << "\r\n"; // Text Value To_Dxf << 50 << "\r\n"; To_Dxf << rotation << "\r\n"; // Text Rotation #if 0 // If "Fit to width", then check if width of text < width specified then change it "center align or left align" if (hAlign == 5) { int xDiff = xAlign - x; int len = text.length(); int t = xDiff/height; if (text.length() < xDiff/height && !leftAlign) { hAlign = 1; xAlign = x+ (xAlign / 2); } else if (text.length() < xDiff/height && leftAlign) { hAlign = 0; xAlign = x; // file.close(); // return; } } #endif To_Dxf << 51 << "\r\n"; To_Dxf << oblique << "\r\n"; // Text Obliqueness To_Dxf << 72 << "\r\n"; To_Dxf << hAlign << "\r\n"; // Text Horizontal Alignment To_Dxf << 73 << "\r\n"; To_Dxf << vAlign << "\r\n"; // Text Vertical Alignment if ((hAlign) || (vAlign)) { // Enter Second Point To_Dxf << 11 << "\r\n"; // XYZ To_Dxf << xAlign << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 21 << "\r\n"; To_Dxf << yAlign << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 31 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates } file.close(); } } } /** @brief Createdxf::drawPolyline Convenience function for draw polyline @param filepath @param poly @param colorcode @param preScaled */ void Createdxf::drawPolyline(const QString &filepath, const QPolygonF &poly, const int &colorcode, bool preScaled) { qreal x,y; if (!filepath.isEmpty()) { QFile file(filepath); if (!file.open(QFile::Append)) { // error message QMessageBox errorFileOpen; errorFileOpen.setText("Error: File "+filepath+" was not written correctly."); errorFileOpen.setInformativeText("Close all Files and Re-Run"); errorFileOpen.exec(); } else { QTextStream To_Dxf(&file); // Draw the Line To_Dxf << 0 << "\r\n"; To_Dxf << "POLYLINE" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(colorcode) << "\r\n"; // Colour Code To_Dxf << 66 << "\r\n"; To_Dxf << 1 << "\r\n"; To_Dxf << 70 << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 20 << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << 30 << "\r\n"; To_Dxf << 0 << "\r\n"; foreach(QPointF p, poly) { if(preScaled) { x = p.x(); y = p.y(); } else { x = p.x() * xScale; y = sheetHeight - (p.y() * yScale); } To_Dxf << 0 << "\r\n"; To_Dxf << "VERTEX" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 70 << "\r\n"; To_Dxf << 32 << "\r\n"; To_Dxf << 10 << "\r\n"; To_Dxf << x << "\r\n"; // X in UCS (User Coordinate System)coordinates To_Dxf << 20 << "\r\n"; To_Dxf << y << "\r\n"; // Y in UCS (User Coordinate System)coordinates To_Dxf << 30 << "\r\n"; To_Dxf << 0.0 << "\r\n"; // Z in UCS (User Coordinate System)coordinates } To_Dxf << 0 << "\r\n"; To_Dxf << "SEQEND" << "\r\n"; To_Dxf << 8 << "\r\n"; To_Dxf << layer << "\r\n"; // Layer name file.close(); } } } /* ================================================ * Majority of calls above here are must be passed * parameters pre=scaled to DXF units * Calls below use Qt scaling, and re-scale them to DXF * ================================================ */ /** @brief Createdxf::drawCircle draw circle in qt format @param fileName @param center @param radius @param colour */ void Createdxf::drawCircle( const QString& fileName, QPointF center, double radius, int colour) { qreal x = center.x() * xScale; qreal y = sheetHeight - center.y() * yScale; qreal r = radius * xScale; drawCircle(fileName,r,x,y,colour); } /** @brief Createdxf::drawLine Convenience function to draw line @param filepath @param line @param colorcode */ void Createdxf::drawLine( const QString &filepath, const QLineF &line, const int &colorcode) { drawLine(filepath, line.p1().x() * xScale, sheetHeight - (line.p1().y() * yScale), line.p2().x() * xScale, sheetHeight - (line.p2().y() * yScale), colorcode); } /** @brief Createdxf::drawEllipse Conveniance function for draw ellipse @param filepath @param rect @param colorcode */ void Createdxf::drawEllipse( const QString &filepath, const QRectF &rect, const int &colorcode) { drawArcEllipse( filepath, rect.topLeft().x() * xScale, sheetHeight - (rect.topLeft().y() * yScale), rect.width() * xScale, rect.height() * yScale, 0, 360, 0, 0, 0, colorcode); } /** @brief Createdxf::drawRectangle Convenience function for draw rectangle @param filepath @param rect @param colorcode */ void Createdxf::drawRectangle( const QString &filepath, const QRectF &rect, const int &colorcode) { //QPolygonF poly(scaleRect(rect)); QPolygonF poly(rect); drawPolyline(filepath,poly,colorcode); } /** @brief Createdxf::drawPolygon Convenience function for draw polygon @param filepath @param poly @param colorcode */ void Createdxf::drawPolygon( const QString &filepath, const QPolygonF &poly, const int &colorcode) { QPolygonF pg = poly; if(!poly.isClosed()) { pg << poly.at(0); // Close it } drawPolyline(filepath,pg,colorcode); } /** @brief Createdxf::drawText draw simple text in dxf format without any alignment specified @param fileName @param text @param point @param height @param rotation @param colour @param xScaleW = 1 */ void Createdxf::drawText( const QString& fileName, const QString& text, QPointF point, double height, double rotation, int colour, double xScaleW) { qreal x = point.x() * xScale; qreal y = sheetHeight - (point.y() * yScale); drawText(fileName,text,x,y,height * yScale,rotation,colour,xScaleW); } void Createdxf::drawArcEllipse( const QString &file_path, QRectF rect, qreal startAngle, qreal spanAngle, QPointF hotspot, qreal rotation_angle, const int &colorcode) { qreal x = rect.x() * xScale; qreal y = sheetHeight - rect.y() * yScale; qreal w = rect.width() * xScale; qreal h = rect.height() * yScale; qreal hotspot_x = hotspot.x() * xScale; qreal hotspot_y = sheetHeight - hotspot.y() * yScale; drawArcEllipse(file_path,x,y,w,h,startAngle,spanAngle,hotspot_x,hotspot_y,rotation_angle,colorcode); } /* * Utility functions */ //static QRectF scaleRect(QRectF rect) //{ // QRectF ro(rect.bottomLeft().x() * Createdxf::xScale, // Createdxf::sheetHeight - (rect.bottomLeft().y() * Createdxf::yScale), // rect.width() * Createdxf::xScale, // rect.height() * Createdxf::yScale); // return ro; //}