diff --git a/src/libs/vdxf/dxiface.cpp b/src/libs/vdxf/dxiface.cpp index 81924d2c9..6ede5f228 100644 --- a/src/libs/vdxf/dxiface.cpp +++ b/src/libs/vdxf/dxiface.cpp @@ -52,6 +52,9 @@ void dx_iface::writeEntity(DRW_Entity *e) case DRW::ASTMNOTCH: dxfW->writeASTMNotch(static_cast(e)); break; + case DRW::ATTDEF: + dxfW->writeATTDEF(static_cast(e)); + break; case DRW::LINE: dxfW->writeLine(static_cast(e)); break; diff --git a/src/libs/vdxf/libdxfrw/drw_entities.cpp b/src/libs/vdxf/libdxfrw/drw_entities.cpp index 8460f7dde..1d191b3fe 100644 --- a/src/libs/vdxf/libdxfrw/drw_entities.cpp +++ b/src/libs/vdxf/libdxfrw/drw_entities.cpp @@ -1359,3 +1359,31 @@ auto DRW_Viewport::parseCode(int code, const std::unique_ptr &reader) return true; } + +auto DRW_ATTDEF::parseCode(int code, const std::unique_ptr &reader) -> bool +{ + switch (code) + { + case 40: + height = reader->getDouble(); + break; + case 1: + text = reader->getString(); + break; + case 2: + name = reader->getString(); + break; + case 3: + promptString = reader->getString(); + break; + case 70: + flags = reader->getInt32(); + break; + case 73: + horizontalAdjustment = reader->getInt32(); + break; + default: + return DRW_Point::parseCode(code, reader); + } + return true; +} diff --git a/src/libs/vdxf/libdxfrw/drw_entities.h b/src/libs/vdxf/libdxfrw/drw_entities.h index faf54c7f6..400c6fd89 100644 --- a/src/libs/vdxf/libdxfrw/drw_entities.h +++ b/src/libs/vdxf/libdxfrw/drw_entities.h @@ -35,7 +35,7 @@ enum ETYPE // E3DSOLID, //encripted propietry data // ACAD_PROXY_ENTITY, ARC, - // ATTDEF, + ATTDEF, // ATTRIB, BLOCK, // and ENDBLK // BODY, //encripted propietry data @@ -274,6 +274,26 @@ public: double angle{0}; /*!< angle, code 50 */ }; +class DRW_ATTDEF : public DRW_Point +{ + SETENTFRIENDS + +public: + DRW_ATTDEF() { eType = DRW::ATTDEF; } + +protected: + auto parseCode(int code, const std::unique_ptr &reader) -> bool override; + +public: + DRW_Coord adjustmentPoint{}; /*!< alignment point, code 11, 21 & 31 */ + double height{0}; /*!< height text, code 40 */ + UTF8STRING text{}; /*!< text string, code 1 */ + UTF8STRING name{}; /*!< name, code 2 */ + UTF8STRING promptString{}; /*!< prompt string, code 3 */ + int flags{0}; /*!< flags, code 70 */ + int horizontalAdjustment{0}; /*!< Horizontal text justification, code 72, default 0 */ +}; + //! Class to handle line entity /*! * Class to handle line entity diff --git a/src/libs/vdxf/libdxfrw/libdxfrw.cpp b/src/libs/vdxf/libdxfrw/libdxfrw.cpp index 16aec3d77..983f000df 100644 --- a/src/libs/vdxf/libdxfrw/libdxfrw.cpp +++ b/src/libs/vdxf/libdxfrw/libdxfrw.cpp @@ -732,6 +732,45 @@ auto dxfRW::writeASTMNotch(DRW_ASTMNotch *ent) -> bool return true; } +auto dxfRW::writeATTDEF(DRW_ATTDEF *ent) -> bool +{ + writer->writeString(0, "ATTDEF"); + + writeEntity(ent); + + if (version > DRW::AC1009) + { + writer->writeString(100, "AcDbText"); + } + + writer->writeDouble(10, ent->basePoint.x); + writer->writeDouble(20, ent->basePoint.y); + if (not qFuzzyIsNull(ent->basePoint.z)) + { + writer->writeDouble(30, ent->basePoint.z); + } + + writer->writeDouble(11, ent->adjustmentPoint.x); + writer->writeDouble(21, ent->adjustmentPoint.y); + if (not qFuzzyIsNull(ent->adjustmentPoint.z)) + { + writer->writeDouble(31, ent->adjustmentPoint.z); + } + + writer->writeDouble(40, ent->height); + writer->writeString(1, ent->text); + + UTF8STRING name = ent->name; + std::replace(name.begin(), name.end(), ' ', '_'); + writer->writeString(2, name); + + writer->writeString(3, ent->promptString); + writer->writeInt16(70, ent->flags); + writer->writeInt16(73, ent->horizontalAdjustment); + + return true; +} + auto dxfRW::writeLine(DRW_Line *ent) -> bool { writer->writeString(0, "LINE"); diff --git a/src/libs/vdxf/libdxfrw/libdxfrw.h b/src/libs/vdxf/libdxfrw/libdxfrw.h index 89df6c4fa..8dce7f1fd 100644 --- a/src/libs/vdxf/libdxfrw/libdxfrw.h +++ b/src/libs/vdxf/libdxfrw/libdxfrw.h @@ -56,6 +56,7 @@ public: auto writeAppId(DRW_AppId *ent) -> bool; auto writePoint(DRW_Point *ent) -> bool; auto writeASTMNotch(DRW_ASTMNotch *ent) -> bool; + auto writeATTDEF(DRW_ATTDEF *ent) -> bool; auto writeLine(DRW_Line *ent) -> bool; auto writeRay(DRW_Ray *ent) -> bool; auto writeXline(DRW_Xline *ent) -> bool; diff --git a/src/libs/vdxf/vdxfengine.cpp b/src/libs/vdxf/vdxfengine.cpp index ffb507d23..9d4781ad4 100644 --- a/src/libs/vdxf/vdxfengine.cpp +++ b/src/libs/vdxf/vdxfengine.cpp @@ -27,7 +27,6 @@ *************************************************************************/ #include "vdxfengine.h" -#include #include #include @@ -59,6 +58,7 @@ #include "../vlayout/vlayoutpoint.h" #include "../vmisc/def.h" #include "dxiface.h" +#include "libdxfrw/drw_entities.h" #if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) #include "../vmisc/compatibility.h" @@ -976,7 +976,7 @@ auto VDxfEngine::ExportToASTM(const QVector &details) -> bool ExportASTMSewLine(detailBlock, detail); ExportASTMInternalLine(detailBlock, detail); ExportASTMInternalCutout(detailBlock, detail); - ExportASTMNotch(detailBlock, detail); + ExportASTMNotches(detailBlock, detail); ExportAAMAGrainline(detailBlock, detail); ExportPieceText(detailBlock, detail); ExportASTMDrill(detailBlock, detail); @@ -1152,90 +1152,135 @@ void VDxfEngine::ExportASTMDrill(const QSharedPointer &detailBloc } //--------------------------------------------------------------------------------------------------------------------- -void VDxfEngine::ExportASTMNotch(const QSharedPointer &detailBlock, const VLayoutPiece &detail) +void VDxfEngine::ExportASTMNotches(const QSharedPointer &detailBlock, const VLayoutPiece &detail) { - if (detail.IsSeamAllowance()) + if (!detail.IsSeamAllowance()) { - const QVector passmarks = detail.GetMappedPassmarks(); - for (const auto &passmark : passmarks) + return; + } + + const QVector passmarks = detail.GetMappedPassmarks(); + for (const auto &passmark : passmarks) + { + DRW_ASTMNotch *notch = ExportASTMNotch(passmark); + DRW_ATTDEF *attdef = ExportASTMNotchDataDependecy(passmark, notch->layer, detail); + detailBlock->ent.push_back(notch); + + if (attdef) { - auto *notch = new DRW_ASTMNotch(); - const QPointF center = passmark.baseLine.p1(); - - notch->basePoint = DRW_Coord(FromPixel(center.x(), m_varInsunits), - FromPixel(GetSize().height() - center.y(), m_varInsunits), - FromPixel(passmark.baseLine.length(), m_varInsunits)); - - notch->angle = passmark.baseLine.angle(); - - switch (passmark.type) - { - case PassmarkLineType::OneLine: - case PassmarkLineType::TwoLines: - case PassmarkLineType::ThreeLines: - // Slit notch - notch->layer = *layer4; - break; - case PassmarkLineType::ExternalVMark: - case PassmarkLineType::InternalVMark: - { // V-Notch - QLineF boundaryLine(passmark.lines.constFirst().p1(), passmark.lines.constLast().p2()); - notch->thickness = FromPixel(boundaryLine.length(), m_varInsunits); // width - notch->layer = *layer4; - break; - } - case PassmarkLineType::TMark: - // T-Notch - notch->thickness = FromPixel(passmark.lines.constLast().length(), m_varInsunits); // width - notch->layer = *layer80; - break; - case PassmarkLineType::BoxMark: - { // Castle Notch - QPointF start = passmark.lines.constFirst().p1(); - QPointF end = passmark.lines.constLast().p2(); - - notch->layer = *layer81; - notch->thickness = FromPixel(QLineF(start, end).length(), m_varInsunits); // width - break; - } - case PassmarkLineType::UMark: - { // U-Notch - QPointF start = passmark.lines.constFirst().p1(); - QPointF end = passmark.lines.constLast().p2(); - - notch->thickness = FromPixel(QLineF(start, end).length(), m_varInsunits); // width - - notch->layer = *layer83; - break; - } - case PassmarkLineType::CheckMark: - { // Check Notch - const QLineF &line1 = passmark.lines.constFirst(); - const QLineF &line2 = passmark.lines.constLast(); - - qreal width = QLineF(line1.p1(), line2.p2()).length(); - - if (not passmark.isClockwiseOpening) - { // a counter clockwise opening - width *= -1; - } - - notch->thickness = FromPixel(width, m_varInsunits); // width - notch->layer = *layer82; - break; - } - case PassmarkLineType::LAST_ONE_DO_NOT_USE: - Q_UNREACHABLE(); - break; - default: - break; - }; - - detailBlock->ent.push_back(notch); + detailBlock->ent.push_back(attdef); } } } +//--------------------------------------------------------------------------------------------------------------------- +auto VDxfEngine::ExportASTMNotch(const VLayoutPassmark &passmark) -> DRW_ASTMNotch * +{ + auto *notch = new DRW_ASTMNotch(); + const QPointF center = passmark.baseLine.p1(); + + notch->basePoint = + DRW_Coord(FromPixel(center.x(), m_varInsunits), FromPixel(GetSize().height() - center.y(), m_varInsunits), + FromPixel(passmark.baseLine.length(), m_varInsunits)); + + notch->angle = passmark.baseLine.angle(); + + switch (passmark.type) + { + case PassmarkLineType::OneLine: + case PassmarkLineType::TwoLines: + case PassmarkLineType::ThreeLines: + // Slit notch + notch->layer = *layer4; + break; + case PassmarkLineType::ExternalVMark: + case PassmarkLineType::InternalVMark: + { // V-Notch + QLineF boundaryLine(passmark.lines.constFirst().p1(), passmark.lines.constLast().p2()); + notch->thickness = FromPixel(boundaryLine.length(), m_varInsunits); // width + notch->layer = *layer4; + break; + } + case PassmarkLineType::TMark: + // T-Notch + notch->thickness = FromPixel(passmark.lines.constLast().length(), m_varInsunits); // width + notch->layer = *layer80; + break; + case PassmarkLineType::BoxMark: + { // Castle Notch + QPointF start = passmark.lines.constFirst().p1(); + QPointF end = passmark.lines.constLast().p2(); + + notch->layer = *layer81; + notch->thickness = FromPixel(QLineF(start, end).length(), m_varInsunits); // width + break; + } + case PassmarkLineType::UMark: + { // U-Notch + QPointF start = passmark.lines.constFirst().p1(); + QPointF end = passmark.lines.constLast().p2(); + + notch->thickness = FromPixel(QLineF(start, end).length(), m_varInsunits); // width + + notch->layer = *layer83; + break; + } + case PassmarkLineType::CheckMark: + { // Check Notch + const QLineF &line1 = passmark.lines.constFirst(); + const QLineF &line2 = passmark.lines.constLast(); + + qreal width = QLineF(line1.p1(), line2.p2()).length(); + + if (not passmark.isClockwiseOpening) + { // a counter clockwise opening + width *= -1; + } + + notch->thickness = FromPixel(width, m_varInsunits); // width + notch->layer = *layer82; + break; + } + case PassmarkLineType::LAST_ONE_DO_NOT_USE: + Q_UNREACHABLE(); + break; + default: + break; + }; + + return notch; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VDxfEngine::ExportASTMNotchDataDependecy(const VLayoutPassmark &passmark, const UTF8STRING ¬chLayer, + const VLayoutPiece &detail) -> DRW_ATTDEF * +{ + QVector boundary = not detail.IsSeamAllowanceBuiltIn() && !passmark.isBuiltIn + ? detail.GetMappedSeamAllowancePoints() + : detail.GetMappedContourPoints(); + + const QPointF center = passmark.baseLine.p1(); + QPointF referencePoint; + if (not NotchPrecedingPoint(boundary, center, referencePoint)) + { + return nullptr; + } + + auto *attdef = new DRW_ATTDEF(); + attdef->layer = not detail.IsSeamAllowanceBuiltIn() && !passmark.isBuiltIn ? *layer1 : *layer14; + attdef->basePoint = DRW_Coord(FromPixel(referencePoint.x(), m_varInsunits), + FromPixel(GetSize().height() - referencePoint.y(), m_varInsunits), 0); + attdef->adjustmentPoint = + DRW_Coord(FromPixel(center.x(), m_varInsunits), FromPixel(GetSize().height() - center.y(), m_varInsunits), 0); + attdef->height = 3.0; + attdef->text = "Link:" + notchLayer; + attdef->name = "Dependency"; + attdef->flags = 2; // this is a constant attribute + attdef->horizontalAdjustment = 3; // aligned (if vertical alignment = 0) + + return attdef; +} + //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::ExportTurnPoints(const QSharedPointer &detailBlock, const QVector &points) const @@ -1335,6 +1380,55 @@ auto VDxfEngine::GetFileNameForLocale() const -> std::string #endif } +//--------------------------------------------------------------------------------------------------------------------- +auto VDxfEngine::NotchPrecedingPoint(const QVector &boundary, QPointF notchBase, QPointF &point) -> bool +{ + if (boundary.count() < 2) + { + return false; + } + + if (VFuzzyComparePoints(boundary.constFirst(), notchBase)) + { + point = boundary.constFirst(); + return true; + } + + if (VFuzzyComparePoints(boundary.constLast(), notchBase)) + { + point = boundary.constLast(); + return true; + } + + QPointF candidatePoint; + qreal bestDistance = INT_MAX; + bool found = false; + + for (qint32 i = 0; i < boundary.count() - 1; ++i) + { + const QPointF cPoint = VGObject::ClosestPoint(QLineF(boundary.at(i), boundary.at(i + 1)), notchBase); + + if (VGObject::IsPointOnLineSegment(cPoint, boundary.at(i), boundary.at(i + 1))) + { + const qreal length = QLineF(notchBase, cPoint).length(); + if (length < bestDistance) + { + candidatePoint = boundary.at(i); + bestDistance = length; + found = true; + } + } + } + + if (found) + { + point = candidatePoint; + return true; + } + + return found; +} + //--------------------------------------------------------------------------------------------------------------------- template auto VDxfEngine::CreateAAMAPolygon(const QVector &polygon, const UTF8STRING &layer, bool forceClosed) -> P * diff --git a/src/libs/vdxf/vdxfengine.h b/src/libs/vdxf/vdxfengine.h index b58c74573..51312806a 100644 --- a/src/libs/vdxf/vdxfengine.h +++ b/src/libs/vdxf/vdxfengine.h @@ -50,6 +50,9 @@ class DRW_Entity; class dx_ifaceBlock; class VLayoutPoint; class DRW_Point; +class DRW_ASTMNotch; +struct VLayoutPassmark; +class DRW_ATTDEF; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) class VTextCodec; @@ -148,7 +151,11 @@ private: void ExportASTMInternalCutout(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportASTMAnnotationText(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportASTMDrill(const QSharedPointer &detailBlock, const VLayoutPiece &detail); - void ExportASTMNotch(const QSharedPointer &detailBlock, const VLayoutPiece &detail); + void ExportASTMNotches(const QSharedPointer &detailBlock, const VLayoutPiece &detail); + + Q_REQUIRED_RESULT auto ExportASTMNotch(const VLayoutPassmark &passmark) -> DRW_ASTMNotch *; + Q_REQUIRED_RESULT auto ExportASTMNotchDataDependecy(const VLayoutPassmark &passmark, const UTF8STRING ¬chLayer, + const VLayoutPiece &detail) -> DRW_ATTDEF *; void ExportTurnPoints(const QSharedPointer &detailBlock, const QVector &points) const; void ExportCurvePoints(const QSharedPointer &detailBlock, const QVector &points) const; @@ -165,6 +172,8 @@ private: static auto FromUnicodeToCodec(const QString &str, VTextCodec *codec) -> std::string; auto GetFileNameForLocale() const -> std::string; + + static auto NotchPrecedingPoint(const QVector &boundary, QPointF notchBase, QPointF &point) -> bool; }; #endif // VDXFENGINE_H