diff --git a/src/Mod/TechDraw/App/CMakeLists.txt b/src/Mod/TechDraw/App/CMakeLists.txt index fb7194c3f7..0f33bcb55d 100644 --- a/src/Mod/TechDraw/App/CMakeLists.txt +++ b/src/Mod/TechDraw/App/CMakeLists.txt @@ -107,8 +107,6 @@ SET(Draw_SRCS DimensionFormatter.h DimensionAutoCorrect.cpp DimensionAutoCorrect.h - GeometryMatcher.cpp - GeometryMatcher.h DrawViewBalloon.cpp DrawViewBalloon.h DrawViewSection.cpp @@ -201,6 +199,8 @@ SET(Geometry_SRCS PropertyCosmeticVertexList.h CosmeticExtension.cpp CosmeticExtension.h + GeometryMatcher.cpp + GeometryMatcher.h ) SET(Python_SRCS diff --git a/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp b/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp index 98d74fa48f..457817a898 100644 --- a/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp +++ b/src/Mod/TechDraw/App/DimensionAutoCorrect.cpp @@ -86,7 +86,6 @@ using DU = DrawUtil; bool DimensionAutoCorrect::referencesHaveValidGeometry(std::vector& referenceState) const { // Base::Console().Message("DAC::referencesHaveValidGeometry()\n"); - ReferenceVector refsAll = getDimension()->getEffectiveReferences(); const std::vector savedGeometry = getDimension()->SavedGeometry.getValues(); @@ -114,6 +113,7 @@ bool DimensionAutoCorrect::referencesHaveValidGeometry(std::vector& refere result = false; referenceState.emplace_back(false); } + iRef++; } return result; } @@ -138,16 +138,6 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector& referenceSta return false; } - std::vector referenceGeometry; - for (auto& entry : refsAll) { - if (entry.hasGeometry()) { - referenceGeometry.push_back(entry.asTopoShape()); - } - else { - referenceGeometry.push_back(Part::TopoShape()); - } - } - size_t iRef {0}; for (const auto& state : referenceState) { if (state) { @@ -158,7 +148,7 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector& referenceSta continue; } - Part::TopoShape temp = savedGeometry.at(iRef); + const Part::TopoShape& temp = savedGeometry.at(iRef); if (temp.isNull()) { result = false; referenceState.at(iRef) = false; @@ -170,7 +160,6 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector& referenceSta // this ref does not point to valid geometry or // the geometry it points to does not match the saved geometry - ReferenceEntry fixedRef = refsAll.at(iRef); // first, look for an exact match to the saved geometry @@ -183,17 +172,17 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector& referenceSta continue; } - // we did not find an exact match, so check for an Similar match + // we did not find an exact match, so check for an similar match success = fix1GeomSimilar(fixedRef, savedGeometry.at(iRef).getShape()); if (success) { - // we did find an Similar match + // we did find an similar match referenceState.at(iRef) = true; repairedRefs.push_back(fixedRef); iRef++; continue; } - // we did not find an Similar match the geometry + // we did not find an similar match the geometry result = false; referenceState.at(iRef) = false; repairedRefs.push_back(fixedRef); @@ -204,60 +193,60 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector& referenceSta return result; } -//! fix a single reference with an exact match to geomToFix -bool DimensionAutoCorrect::fix1GeomExact(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const +//! fix a single reference with an exact match to geomToMatch +bool DimensionAutoCorrect::fix1GeomExact(ReferenceEntry& refToFix, const TopoDS_Shape &geomToMatch) const { // Base::Console().Message("DAC::fix1GeomExact()\n"); ReferenceEntry fixedRef = refToFix; - Part::TopoShape topoShapeToFix(geomToFix); + Part::TopoShape topoShapeToMatch(geomToMatch); bool success {false}; if (refToFix.is3d()) { if (!refToFix.getObject() && m_3dObjectCache.empty()) { return false; } - if (geomToFix.ShapeType() == TopAbs_VERTEX) { - success = findExactVertex3d(refToFix, topoShapeToFix); + if (geomToMatch.ShapeType() == TopAbs_VERTEX) { + success = findExactVertex3d(refToFix, topoShapeToMatch); } else { - success = findExactEdge3d(refToFix, topoShapeToFix); + success = findExactEdge3d(refToFix, topoShapeToMatch); } } else { - if (geomToFix.ShapeType() == TopAbs_VERTEX) { - success = findExactVertex2d(refToFix, topoShapeToFix); + if (geomToMatch.ShapeType() == TopAbs_VERTEX) { + success = findExactVertex2d(refToFix, topoShapeToMatch); } else { - success = findExactEdge2d(refToFix, topoShapeToFix); + success = findExactEdge2d(refToFix, topoShapeToMatch); } } return success; } -//! fix a single reference with an Similar match to geomToFix -bool DimensionAutoCorrect::fix1GeomSimilar(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const +//! fix a single reference with an Similar match to geomToMatch +bool DimensionAutoCorrect::fix1GeomSimilar(ReferenceEntry& refToFix, const TopoDS_Shape &geomToMatch) const { // Base::Console().Message("DAC::fix1GeomSimilar()\n"); - Part::TopoShape topoShapeToFix(geomToFix); + Part::TopoShape topoShapeToMatch(geomToMatch); bool success {false}; if (refToFix.is3d()) { if (!refToFix.getObject() && m_3dObjectCache.empty()) { // can't fix this. nothing to compare. return false; } - if (geomToFix.ShapeType() == TopAbs_VERTEX) { - success = findSimilarVertex3d(refToFix, topoShapeToFix); + if (geomToMatch.ShapeType() == TopAbs_VERTEX) { + success = findSimilarVertex3d(refToFix, topoShapeToMatch); } else { - success = findSimilarEdge3d(refToFix, topoShapeToFix); + success = findSimilarEdge3d(refToFix, topoShapeToMatch); } } else { - if (geomToFix.ShapeType() == TopAbs_VERTEX) { - success = findSimilarVertex2d(refToFix, topoShapeToFix); + if (geomToMatch.ShapeType() == TopAbs_VERTEX) { + success = findSimilarVertex2d(refToFix, topoShapeToMatch); } else { - success = findSimilarEdge2d(refToFix, topoShapeToFix); + success = findSimilarEdge2d(refToFix, topoShapeToMatch); } } return success; @@ -267,7 +256,7 @@ bool DimensionAutoCorrect::fix1GeomSimilar(ReferenceEntry& refToFix, TopoDS_Shap //! search the view for a 2d vertex that is the same as the saved reference geometry //! and return a reference pointing to the matching vertex bool DimensionAutoCorrect::findExactVertex2d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findExactVertex2d()\n"); getMatcher()->setPointTolerance(EWTOLERANCE); @@ -284,32 +273,29 @@ bool DimensionAutoCorrect::findExactVertex2d(ReferenceEntry& refToFix, return false; } -//! search the view for a 2d edge that is the same as the saved reference geometry + +//! search the view for a 2d edge that is the same as the saved reference geometry (from DVD::SavedGeometry) //! and return a reference pointing to the matching edge. -bool DimensionAutoCorrect::findExactEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const +bool DimensionAutoCorrect::findExactEdge2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findExactEdge2d()\n"); - double scale = getDimension()->getViewPart()->getScale(); - BaseGeomPtrVector gEdgeAll = getDimension()->getViewPart()->getEdgeGeometry(); - int iEdge {0}; - for (auto& edge : gEdgeAll) { - Part::TopoShape temp = edge->asTopoShape(scale); - bool isSame = getMatcher()->compareGeometry(refGeom, temp); - if (isSame) { - refToFix.setSubName(std::string("Edge") + std::to_string(iEdge)); + auto refObj = refToFix.getObject(); + auto refDvp = dynamic_cast(refObj); + if (refDvp) { + ReferenceEntry fixedRef = searchViewForExactEdge(refDvp, refGeom); + if (fixedRef.getObject()) { + refToFix = fixedRef; return true; } - iEdge++; } - - // no match, return the input reference + // no match return false; } //! search the model for a 3d vertex that is the same as the saved reference geometry //! and return a reference pointing to the matching vertex bool DimensionAutoCorrect::findExactVertex3d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findExactVertex3d()\n"); getMatcher()->setPointTolerance(EWTOLERANCE); @@ -339,7 +325,7 @@ bool DimensionAutoCorrect::findExactVertex3d(ReferenceEntry& refToFix, //! search the model for a 3d edge that is the same as the saved reference geometry //! and return a reference pointing to the matching edge. -bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const +bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findExactEdge3d() - cache: %d\n", m_3dObjectCache.size()); // first, try to find a match in the referenced object @@ -375,24 +361,24 @@ bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, Part::TopoS //! search the view for a vertex that is within a tolerance of the saved reference geometry //! and return a reference pointing to the matching vertex bool DimensionAutoCorrect::findSimilarVertex2d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findSimilarVertex2d()\n"); (void)refToFix; (void)refGeom; - Base::Console().Message("DAC::findSimilarVertex2d is not implemented yet\n"); + // Base::Console().Message("DAC::findSimilarVertex2d is not implemented yet\n"); return false; } //! search the view for a 2d edge that is similar to the saved reference geometry //! and return a reference pointing to the similar edge. bool DimensionAutoCorrect::findSimilarEdge2d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findSimilarEdge2d()\n"); (void)refToFix; (void)refGeom; - Base::Console().Message("DAC::findSimilarEdge2d is not implemented yet\n"); + // Base::Console().Message("DAC::findSimilarEdge2d is not implemented yet\n"); return false; } @@ -400,12 +386,12 @@ bool DimensionAutoCorrect::findSimilarEdge2d(ReferenceEntry& refToFix, //! a tolerance of the saved reference geometry and return a reference pointing //! to the matching vertex bool DimensionAutoCorrect::findSimilarVertex3d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findSimilarVertex3d()\n"); (void)refToFix; (void)refGeom; - Base::Console().Message("DAC::findSimilarVertex3d is not implemented yet\n"); + // Base::Console().Message("DAC::findSimilarVertex3d is not implemented yet\n"); return false; } @@ -413,20 +399,21 @@ bool DimensionAutoCorrect::findSimilarVertex3d(ReferenceEntry& refToFix, //! similar to the saved reference geometry and return a reference pointing //! to the similar edge bool DimensionAutoCorrect::findSimilarEdge3d(ReferenceEntry& refToFix, - Part::TopoShape refGeom) const + const Part::TopoShape& refGeom) const { // Base::Console().Message("DAC::findSimilarEdge3d(%s)\n", refToFix.getObjectName().c_str()); (void)refToFix; (void)refGeom; - Base::Console().Message("DAC::findSimilarEdge3d is not implemented yet\n"); + // Base::Console().Message("DAC::findSimilarEdge3d is not implemented yet\n"); return false; } //! compare the geometry pointed to by a reference to the corresponding saved geometry -bool DimensionAutoCorrect::isMatchingGeometry(ReferenceEntry ref, - Part::TopoShape savedGeometry) const +bool DimensionAutoCorrect::isMatchingGeometry(const ReferenceEntry& ref, + const Part::TopoShape& savedGeometry) const { - Part::TopoShape temp = ref.asTopoShape(); + // Base::Console().Message("DAC::isMatchingGeometry()\n"); + Part::TopoShape temp = ref.asCanonicalTopoShape(); if (temp.isNull()) { // this shouldn't happen as we already know that this ref points to valid geometry return false; @@ -443,7 +430,7 @@ bool DimensionAutoCorrect::isMatchingGeometry(ReferenceEntry ref, //! an exact match for phase 1 (GeometryMatcher), but in phase 2 (GeometryGuesser) //! a similar match will be allowed. ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj, - Part::TopoShape refVertex, + const Part::TopoShape& refVertex, bool exact) const { (void)exact; @@ -455,7 +442,7 @@ ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj, auto vertsAll = getDimension()->getVertexes(shape3d); size_t iVert {1}; for (auto& vert : vertsAll) { - bool isSame = getMatcher()->compareGeometry(refVertex, vert); + bool isSame = getMatcher()->compareGeometry(vert, refVertex); if (isSame) { auto newSubname = std::string("Vertex") + std::to_string(iVert); return {obj, newSubname, getDimension()->getDocument()}; @@ -469,18 +456,19 @@ ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj, //! search View (2d part display) for a match to refVertex. This can be an //! exact or Similar match depending on the setting of exact. ReferenceEntry DimensionAutoCorrect::searchViewForVert(DrawViewPart* obj, - Part::TopoShape refVertex, + const Part::TopoShape& refVertex, bool exact) const { + // Base::Console().Message("DAC::searchViewForVert()\n"); (void)exact; - double scale = getDimension()->getViewPart()->getScale(); std::vector gVertexAll = getDimension()->getViewPart()->getVertexGeometry(); getMatcher()->setPointTolerance(EWTOLERANCE); int iVertex = 0; for (auto& vert : gVertexAll) { - Part::TopoShape temp = vert->asTopoShape(scale); - bool isSame = getMatcher()->compareGeometry(refVertex, temp); + // vert is in display form - scaled and rotated + Part::TopoShape temp = ReferenceEntry::asCanonicalTopoShape(vert->asTopoShape(), *obj); + bool isSame = getMatcher()->compareGeometry(temp, refVertex); if (isSame) { auto newSubname = std::string("Vertex") + std::to_string(iVertex); return {obj, newSubname, getDimension()->getDocument()}; @@ -492,14 +480,15 @@ ReferenceEntry DimensionAutoCorrect::searchViewForVert(DrawViewPart* obj, //! search View (2d part display) for an exact match to refEdge. ReferenceEntry DimensionAutoCorrect::searchViewForExactEdge(DrawViewPart* obj, - Part::TopoShape refEdge) const + const Part::TopoShape& refEdge) const { // Base::Console().Message("DAC::searchViewForExactEdge()\n"); - double scale = getDimension()->getViewPart()->getScale(); auto gEdgeAll = getDimension()->getViewPart()->getEdgeGeometry(); int iEdge {0}; for (auto& edge : gEdgeAll) { - Part::TopoShape temp = edge->asTopoShape(scale); + // edge is scaled and rotated. we need it in the same scale/rotate state as + // the reference edge in order to match. + Part::TopoShape temp = ReferenceEntry::asCanonicalTopoShape(edge->asTopoShape(), *obj); bool isSame = getMatcher()->compareGeometry(refEdge, temp); if (isSame) { auto newSubname = std::string("Edge") + std::to_string(iEdge); @@ -513,7 +502,7 @@ ReferenceEntry DimensionAutoCorrect::searchViewForExactEdge(DrawViewPart* obj, //! search View (2d part display) for an edge that is similar to refEdge ReferenceEntry DimensionAutoCorrect::searchViewForSimilarEdge(DrawViewPart* obj, - Part::TopoShape refEdge) const + const Part::TopoShape& refEdge) const { // Base::Console().Message("DAC::searchViewForSimilarEdge()\n"); (void)obj; @@ -525,7 +514,7 @@ ReferenceEntry DimensionAutoCorrect::searchViewForSimilarEdge(DrawViewPart* obj, //! search model for for a 3d edge that is a match to refEdge //! note that only the exact match is implemented in phase 1 ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj, - Part::TopoShape refEdge, + const Part::TopoShape& refEdge, bool exact) const { // Base::Console().Message("DAC::searchObjForEdge(%s)\n", obj->Label.getValue()); @@ -533,13 +522,12 @@ ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj, auto shape3d = Part::Feature::getShape(obj); if (shape3d.IsNull()) { // how to handle this? - // Base::Console().Message("DAC::searchObjForEdge - object shape is null\n"); return {}; } auto edgesAll = getDimension()->getEdges(shape3d); size_t iEdge {1}; for (auto& edge : edgesAll) { - bool isSame = getMatcher()->compareGeometry(refEdge, edge); + bool isSame = getMatcher()->compareGeometry(edge, refEdge); if (isSame) { auto newSubname = std::string("Edge") + std::to_string(iEdge); return {obj, newSubname, getDimension()->getDocument()}; @@ -563,7 +551,7 @@ bool DimensionAutoCorrect::fixBrokenReferences(ReferenceVector& fixedReferences) continue; } // - TopoDS_Shape geomShape = geom.getShape(); + const TopoDS_Shape& geomShape = geom.getShape(); for (auto& objectName : m_3dObjectCache) { auto object3d = getDimension()->getDocument()->getObject(objectName.c_str()); if (!object3d) { @@ -594,3 +582,4 @@ GeometryMatcher* DimensionAutoCorrect::getMatcher() const { return getDimension()->getMatcher(); } + diff --git a/src/Mod/TechDraw/App/DimensionAutoCorrect.h b/src/Mod/TechDraw/App/DimensionAutoCorrect.h index a3e154d490..641f0df0f6 100644 --- a/src/Mod/TechDraw/App/DimensionAutoCorrect.h +++ b/src/Mod/TechDraw/App/DimensionAutoCorrect.h @@ -42,12 +42,9 @@ class GeometryMatcher; class TechDrawExport DimensionAutoCorrect { public: - DimensionAutoCorrect() - {} - explicit DimensionAutoCorrect(DrawViewDimension* dim) - { - m_dimension = dim; - } + DimensionAutoCorrect() = default; + explicit DimensionAutoCorrect(DrawViewDimension* dim) : + m_dimension(dim) {} ~DimensionAutoCorrect() = default; bool referencesHaveValidGeometry(std::vector& referenceState) const; @@ -61,31 +58,30 @@ public: bool fixBrokenReferences(ReferenceVector& fixedReferences) const; private: - bool fix1GeomExact(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const; - bool fix1GeomSimilar(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const; + bool fix1GeomExact(ReferenceEntry& refToFix, const TopoDS_Shape& geomToMatch) const; + bool fix1GeomSimilar(ReferenceEntry& refToFix, const TopoDS_Shape& geomToMatch) const; - bool findExactVertex2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findExactEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findExactVertex3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findExactEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; + bool findExactVertex2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findExactEdge2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findExactVertex3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findExactEdge3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; - bool findSimilarVertex2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findSimilarEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findSimilarVertex3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; - bool findSimilarEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const; + bool findSimilarVertex2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findSimilarEdge2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findSimilarVertex3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; + bool findSimilarEdge3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const; ReferenceEntry - searchObjForVert(App::DocumentObject* obj, Part::TopoShape refVertex, bool exact = true) const; + searchObjForVert(App::DocumentObject* obj, const Part::TopoShape& refVertex, bool exact = true) const; ReferenceEntry - searchViewForVert(DrawViewPart* obj, Part::TopoShape refVertex, bool exact = true) const; + searchViewForVert(DrawViewPart* obj, const Part::TopoShape& refVertex, bool exact = true) const; ReferenceEntry - searchObjForEdge(App::DocumentObject* obj, Part::TopoShape refEdge, bool exact = true) const; + searchObjForEdge(App::DocumentObject* obj, const Part::TopoShape& refEdge, bool exact = true) const; - ReferenceEntry searchViewForExactEdge(DrawViewPart* obj, Part::TopoShape refEdge) const; - ReferenceEntry searchViewForSimilarEdge(DrawViewPart* obj, Part::TopoShape refEdge) const; + ReferenceEntry searchViewForExactEdge(DrawViewPart* obj, const Part::TopoShape& refEdge) const; + ReferenceEntry searchViewForSimilarEdge(DrawViewPart* obj, const Part::TopoShape& refEdge) const; - - bool isMatchingGeometry(ReferenceEntry ref, Part::TopoShape savedGeometry) const; + bool isMatchingGeometry(const ReferenceEntry& ref, const Part::TopoShape& savedGeometry) const; DrawViewDimension* getDimension() const { @@ -93,7 +89,7 @@ private: } GeometryMatcher* getMatcher() const; - DrawViewDimension* m_dimension; + DrawViewDimension* m_dimension{nullptr}; std::set m_3dObjectCache; }; diff --git a/src/Mod/TechDraw/App/DimensionGeometry.cpp b/src/Mod/TechDraw/App/DimensionGeometry.cpp index 9ed0751fcd..60186d6b96 100644 --- a/src/Mod/TechDraw/App/DimensionGeometry.cpp +++ b/src/Mod/TechDraw/App/DimensionGeometry.cpp @@ -28,6 +28,7 @@ #endif #include +#include #include "DimensionGeometry.h" #include "DrawUtil.h" @@ -117,6 +118,43 @@ void pointPair::dump(const std::string& text) const DU::formatVector(first()).c_str(), DU::formatVector(second()).c_str()); } +//! return unscaled, unrotated version of this pointPair. caller is responsible for +//! for ensuring this pointPair is in scaled, rotated form before calling this method. +pointPair pointPair::toCanonicalForm(DrawViewPart* dvp) const +{ + pointPair result; + // invert points? + result.m_first = CosmeticVertex::makeCanonicalPoint(dvp, m_first); + result.m_second = CosmeticVertex::makeCanonicalPoint(dvp, m_second); + result.m_overrideFirst = CosmeticVertex::makeCanonicalPoint(dvp, m_overrideFirst); + result.m_overrideSecond = CosmeticVertex::makeCanonicalPoint(dvp, m_overrideSecond); + return result; +} + +//! return scaled and rotated version of this pointPair. caller is responsible for +//! for ensuring this pointPair is in canonical form before calling this method. +pointPair pointPair::toDisplayForm(DrawViewPart* dvp) const +{ + pointPair result; + + // invert points? + result.m_first = m_first * dvp->getScale(); + result.m_second = m_second * dvp->getScale(); + result.m_overrideFirst = m_overrideFirst * dvp->getScale(); + result.m_overrideSecond = m_overrideSecond * dvp->getScale(); + auto rotationDeg = dvp->Rotation.getValue(); + if (rotationDeg != 0.0) { + auto rotationRad = Base::toRadians(rotationDeg); + result.m_first.RotateZ(rotationRad); + result.m_second.RotateZ(rotationRad); + result.m_overrideFirst.RotateZ(rotationRad); + result.m_overrideSecond.RotateZ(rotationRad); + } + return result; +} + + + anglePoints::anglePoints() { m_ends.first(Base::Vector3d(0.0, 0.0, 0.0)); @@ -168,6 +206,30 @@ void anglePoints::invertY() m_vertex = DU::invertY(m_vertex); } +//! return unscaled, unrotated version of this anglePoints. caller is responsible for +//! for ensuring this anglePoints is in scaled, rotated form before calling this method. +anglePoints anglePoints::toCanonicalForm(DrawViewPart* dvp) const +{ + anglePoints result; + result.m_ends = m_ends.toCanonicalForm(dvp); + result.m_vertex = CosmeticVertex::makeCanonicalPoint(dvp, m_vertex); + return result; +} + +//! return scaled and rotated version of this anglePoints. caller is responsible for +//! for ensuring this anglePoints is in canonical form before calling this method. +anglePoints anglePoints::toDisplayForm(DrawViewPart* dvp) const +{ + anglePoints result; + result.m_ends = m_ends.toDisplayForm(dvp); + result.m_vertex = m_vertex * dvp->getScale(); + auto rotationDeg = dvp->Rotation.getValue(); + if (rotationDeg != 0.0) { + auto rotationRad = Base::toRadians(rotationDeg); + result.m_vertex.RotateZ(rotationRad); + } + return result; +} void anglePoints::dump(const std::string& text) const { Base::Console().Message("anglePoints - %s\n", text.c_str()); @@ -252,6 +314,39 @@ void arcPoints::invertY() midArc = DU::invertY(midArc); } +//! return scaled and rotated version of this arcPoints. caller is responsible for +//! for ensuring this arcPoints is in canonical form before calling this method. +arcPoints arcPoints::toDisplayForm(DrawViewPart* dvp) const +{ + arcPoints result; + result.onCurve = onCurve.toDisplayForm(dvp); + result.arcEnds = arcEnds.toDisplayForm(dvp); + result.center = center * dvp->getScale(); + result.midArc = midArc * dvp->getScale(); + result.radius = radius * dvp->getScale(); + auto rotationDeg = dvp->Rotation.getValue(); + if (rotationDeg != 0.0) { + auto rotationRad = Base::toRadians(rotationDeg); + result.center.RotateZ(rotationRad); + result.midArc.RotateZ(rotationRad); + } + return result; +} + +//! return unscaled, unrotated version of this arcPoints. caller is responsible for +//! for ensuring this arcPoints is in scaled, rotated form before calling this method. +arcPoints arcPoints::toCanonicalForm(DrawViewPart* dvp) const +{ + arcPoints result; + result.onCurve = onCurve.toCanonicalForm(dvp); + result.arcEnds = arcEnds.toCanonicalForm(dvp); + result.center = CosmeticVertex::makeCanonicalPoint(dvp, center); + result.midArc = CosmeticVertex::makeCanonicalPoint(dvp, midArc); + result.radius = radius / dvp->getScale(); + return result; +} + + void arcPoints::dump(const std::string& text) const { Base::Console().Message("arcPoints - %s\n", text.c_str()); diff --git a/src/Mod/TechDraw/App/DimensionGeometry.h b/src/Mod/TechDraw/App/DimensionGeometry.h index f21f85f305..3a651dbe48 100644 --- a/src/Mod/TechDraw/App/DimensionGeometry.h +++ b/src/Mod/TechDraw/App/DimensionGeometry.h @@ -79,6 +79,10 @@ public: void scale(double factor); void dump(const std::string& text) const; + pointPair toCanonicalForm(DrawViewPart* dvp) const; + pointPair toDisplayForm(DrawViewPart* dvp) const; + + private: Base::Vector3d m_first; Base::Vector3d m_second; @@ -115,6 +119,10 @@ public: void invertY(); void dump(const std::string& text) const; + anglePoints toCanonicalForm(DrawViewPart* dvp) const; + anglePoints toDisplayForm(DrawViewPart* dvp) const; + + private: pointPair m_ends; Base::Vector3d m_vertex; @@ -135,6 +143,9 @@ public: void invertY(); void dump(const std::string& text) const; + arcPoints toCanonicalForm(DrawViewPart* dvp) const; + arcPoints toDisplayForm(DrawViewPart* dvp) const; + //TODO: setters and getters bool isArc; double radius; diff --git a/src/Mod/TechDraw/App/DimensionReferences.cpp b/src/Mod/TechDraw/App/DimensionReferences.cpp index 0cc62c8423..3cfed7f2f8 100644 --- a/src/Mod/TechDraw/App/DimensionReferences.cpp +++ b/src/Mod/TechDraw/App/DimensionReferences.cpp @@ -42,9 +42,11 @@ #include "DrawUtil.h" #include "DrawViewPart.h" #include "ShapeUtils.h" +#include "CosmeticVertex.h" using namespace TechDraw; using DU = DrawUtil; +using SU = ShapeUtils; ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document) @@ -60,6 +62,7 @@ ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, std::string subN } } + ReferenceEntry::ReferenceEntry(const ReferenceEntry& other) { setObject(other.getObject()); @@ -72,6 +75,9 @@ ReferenceEntry::ReferenceEntry(const ReferenceEntry& other) ReferenceEntry& ReferenceEntry::operator=(const ReferenceEntry& otherRef) { + if (this == &otherRef) { + return *this; + } setObject(otherRef.getObject()); setSubName(otherRef.getSubName()); setObjectName(otherRef.getObjectName()); @@ -87,51 +93,19 @@ TopoDS_Shape ReferenceEntry::getGeometry() const // first, make sure the object has not been deleted! App::DocumentObject* obj = getDocument()->getObject(getObjectName().c_str()); if (!obj) { - Base::Console().Message("RE::getGeometry - %s no longer exists!\n", getObjectName().c_str()); return {}; } if (getSubName().empty()) { - Base::Console().Message("RE::getGeometry - Reference has no subelement!\n"); return {}; } if ( getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) { - // Base::Console().Message("RE::getGeometry - getting 2d geometry\n"); - std::string gType; - try { - auto dvp = static_cast(getObject()); - gType = geomType(); - if (gType == "Vertex") { - // getVertex throws on not found, but we want to return null - // shape - auto vgeom = dvp->getVertex(getSubName()); - if (!vgeom) { - return {}; - } - return vgeom->getOCCVertex(); - } - if (gType == "Edge") { - auto egeom = dvp->getEdge(getSubName()); - if (!egeom) { - return {}; - } - return egeom->getOCCEdge(); - } - if (gType == "Face") { - auto fgeom = dvp->getFace(getSubName()); - if (!fgeom) { - return {}; - } - return fgeom->toOccFace(); - } - } - catch (...) { - Base::Console().Message("RE::getGeometry - no shape for dimension 2d reference - gType: **%s**\n", gType.c_str()); - return {}; - } + // 2d geometry from DrawViewPart will be rotated and scaled + return getGeometry2d(); } + // 3d geometry Part::TopoShape shape = Part::Feature::getTopoShape(getObject()); auto geoFeat = dynamic_cast(getObject()); if (geoFeat) { @@ -145,6 +119,48 @@ TopoDS_Shape ReferenceEntry::getGeometry() const return shape.getSubShape(getSubName().c_str()); } + +//! get a shape for this 2d reference +TopoDS_Shape ReferenceEntry::getGeometry2d() const +{ + // Base::Console().Message("RE::getGeometry2d()\n"); + std::string gType; + try { + auto dvp = static_cast(getObject()); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast + gType = geomType(); + if (gType == "Vertex") { + // getVertex throws on not found, but we want to return null + // shape + auto vgeom = dvp->getVertex(getSubName()); + if (!vgeom) { + return {}; + } + return vgeom->getOCCVertex(); + } + if (gType == "Edge") { + auto egeom = dvp->getEdge(getSubName()); + if (!egeom) { + return {}; + } + return egeom->getOCCEdge(); + } + if (gType == "Face") { + auto fgeom = dvp->getFace(getSubName()); + if (!fgeom) { + return {}; + } + return fgeom->toOccFace(); + } + } + catch (...) { + Base::Console().Message("RE::getGeometry2d - no shape for dimension 2d reference - gType: **%s**\n", gType.c_str()); + return {}; + } + + return {}; +} + + std::string ReferenceEntry::getSubName(bool longForm) const { if (longForm) { @@ -158,6 +174,7 @@ std::string ReferenceEntry::getSubName(bool longForm) const return workingSubName; } + App::DocumentObject* ReferenceEntry::getObject() const { if (!getDocument()) { @@ -171,13 +188,14 @@ App::DocumentObject* ReferenceEntry::getObject() const return obj; } + +//! return the reference geometry as a Part::TopoShape. Part::TopoShape ReferenceEntry::asTopoShape() const { -// Base::Console().Message("RE::asTopoShape()\n"); + // Base::Console().Message("RE::asTopoShape()\n"); TopoDS_Shape geom = getGeometry(); if (geom.IsNull()) { // throw Base::RuntimeError("Dimension Reference has null geometry"); - Base::Console().Message("RE::asTopoShape - reference geometry is null\n"); return {}; } if (geom.ShapeType() == TopAbs_VERTEX) { @@ -191,28 +209,48 @@ Part::TopoShape ReferenceEntry::asTopoShape() const throw Base::RuntimeError("Dimension Reference has unsupported geometry"); } -Part::TopoShape ReferenceEntry::asTopoShapeVertex(TopoDS_Vertex& vert) const +//! returns unscaled, unrotated version of inShape. inShape is assumed to be a 2d shape, but this is not enforced. +Part::TopoShape ReferenceEntry::asCanonicalTopoShape() const { - Base::Vector3d point = DU::toVector3d(BRep_Tool::Pnt(vert)); - if (!is3d()) { - auto dvp = static_cast(getObject()); - point = point / dvp->getScale(); + // Base::Console().Message("RE::asCanonicalTopoShape()\n"); + if (is3d()) { + return asTopoShape(); } - BRepBuilderAPI_MakeVertex mkVert(DU::togp_Pnt(point)); - return { mkVert.Vertex() }; + + // this is a 2d reference + auto dvp = static_cast(getObject()); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast + auto rawTopoShape = asTopoShape(); + return ReferenceEntry::asCanonicalTopoShape(rawTopoShape, *dvp); } -Part::TopoShape ReferenceEntry::asTopoShapeEdge(TopoDS_Edge &edge) const + +//! static public method returns unscaled, unrotated version of inShape. inShape is assumed to be a 2d shape, +//! but this is not enforced. 3d shapes should not be made canonical. +//! 2d shapes are inverted in Y direction and need to be inverted before and after rotation +//! operations. +Part::TopoShape ReferenceEntry::asCanonicalTopoShape(const Part::TopoShape& inShape, const DrawViewPart& dvp) { -// Base::Console().Message("RE::asTopoShapeEdge()\n"); - TopoDS_Edge unscaledEdge = edge; - if (!is3d()) { - // 2d reference - projected and scaled. scale might have changed, so we need to unscale - auto dvp = static_cast(getObject()); - TopoDS_Shape unscaledShape = ShapeUtils::scaleShape(edge, 1.0 / dvp->getScale()); - unscaledEdge = TopoDS::Edge(unscaledShape); + // Base::Console().Message("RE::(static)asCanonicalTopoShape()\n"); + gp_Ax2 OXYZ; + auto unscaledShape = SU::scaleShape(inShape.getShape(), 1.0 / dvp.getScale()); + if (dvp.Rotation.getValue() != 0.0) { + auto rotationDeg = dvp.Rotation.getValue(); + unscaledShape = SU::invertGeometry(unscaledShape); + unscaledShape = SU::rotateShape(unscaledShape, OXYZ, -rotationDeg); + unscaledShape = SU::invertGeometry(unscaledShape); } - return { unscaledEdge }; + return {unscaledShape}; +} + + +Part::TopoShape ReferenceEntry::asTopoShapeVertex(const TopoDS_Vertex& vert) +{ + return { vert }; +} + +Part::TopoShape ReferenceEntry::asTopoShapeEdge(const TopoDS_Edge &edge) +{ + return { edge }; } std::string ReferenceEntry::geomType() const @@ -226,27 +264,22 @@ bool ReferenceEntry::isWholeObject() const return getSubName().empty(); } +//! true if this reference point to 3d model geometry bool ReferenceEntry::is3d() const { - if (getObject() && - getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) && - !getSubName().empty()) { - // this is a well formed 2d reference + if (!getObject()) { + // we should really fail here? + return false; + } + if (getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { return false; } - if (getObject() && - getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) && - getSubName().empty()) { - // this is a broken 3d reference, so it should be treated as 3d - return true; - } - - // either we have no object or we have an object and it is a 3d object return true; } -//! check if this reference has valid geometry in the model + +//! true if the target of this reference has a shape bool ReferenceEntry::hasGeometry() const { // Base::Console().Message("RE::hasGeometry()\n"); @@ -256,33 +289,38 @@ bool ReferenceEntry::hasGeometry() const if ( getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) { // 2d reference - auto dvp = static_cast(getObject()); - if (getSubName().empty()) { - return false; - } - int geomNumber = DU::getIndexFromName(getSubName()); - std::string gType = geomType(); - if (gType == "Vertex") { - auto vert = dvp->getProjVertexByIndex(geomNumber); - if (vert) { - return true; - } - } else if (gType == "Edge") { - auto edge = dvp->getGeomByIndex(geomNumber); - if (edge) { - return true; - } - } - // if we ever have dimensions for faces, add something here. - return false; + return hasGeometry2d(); } // 3d reference auto shape = Part::Feature::getTopoShape(getObject()); auto subShape = shape.getSubShape(getSubName().c_str()); - if (!subShape.IsNull()) { - return true; - } + return !subShape.IsNull(); +} + + +//! check if this 2d reference has valid geometry in the model +bool ReferenceEntry::hasGeometry2d() const +{ + auto dvp = static_cast(getObject()); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast + if (getSubName().empty()) { + return false; + } + int geomNumber = DU::getIndexFromName(getSubName()); + std::string gType = geomType(); + if (gType == "Vertex") { + auto vert = dvp->getProjVertexByIndex(geomNumber); + if (vert) { + return true; + } + } else if (gType == "Edge") { + auto edge = dvp->getGeomByIndex(geomNumber); + if (edge) { + return true; + } + } return false; } + + diff --git a/src/Mod/TechDraw/App/DimensionReferences.h b/src/Mod/TechDraw/App/DimensionReferences.h index e9c41ed80e..19b1a11681 100644 --- a/src/Mod/TechDraw/App/DimensionReferences.h +++ b/src/Mod/TechDraw/App/DimensionReferences.h @@ -47,12 +47,13 @@ class TopoShape; namespace TechDraw { +class DrawViewPart; //a convenient way of handling object+subName references class TechDrawExport ReferenceEntry { public: - ReferenceEntry() {}; + ReferenceEntry() = default; ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document = nullptr); ReferenceEntry(const ReferenceEntry& other); ~ReferenceEntry() = default; @@ -62,9 +63,9 @@ public: App::DocumentObject* getObject() const; void setObject(App::DocumentObject* docObj) { m_object = docObj; } std::string getSubName(bool longForm = false) const; - void setSubName(std::string subName) { m_subName = subName; } + void setSubName(const std::string& subName) { m_subName = subName; } std::string getObjectName() const { return m_objectName; } - void setObjectName(std::string name) { m_objectName = name; } + void setObjectName(const std::string& name) { m_objectName = name; } App::Document* getDocument() const { return m_document; } void setDocument(App::Document* document) { m_document = document; } @@ -73,17 +74,22 @@ public: bool isWholeObject() const; Part::TopoShape asTopoShape() const; + Part::TopoShape asCanonicalTopoShape() const; + static Part::TopoShape asCanonicalTopoShape(const Part::TopoShape& inShape, const DrawViewPart& dvp); bool is3d() const; bool hasGeometry() const; private: - Part::TopoShape asTopoShapeVertex(TopoDS_Vertex &vert) const; - Part::TopoShape asTopoShapeEdge(TopoDS_Edge& edge) const; + bool hasGeometry2d() const; + TopoDS_Shape getGeometry2d() const; + + static Part::TopoShape asTopoShapeVertex(const TopoDS_Vertex &vert); + static Part::TopoShape asTopoShapeEdge(const TopoDS_Edge& edge); App::DocumentObject* m_object{nullptr}; - std::string m_subName{""}; - std::string m_objectName{""}; + std::string m_subName; + std::string m_objectName; App::Document* m_document{nullptr}; }; diff --git a/src/Mod/TechDraw/App/DrawUtil.cpp b/src/Mod/TechDraw/App/DrawUtil.cpp index b28bb8cd67..78970cc23a 100644 --- a/src/Mod/TechDraw/App/DrawUtil.cpp +++ b/src/Mod/TechDraw/App/DrawUtil.cpp @@ -1944,7 +1944,7 @@ void DrawUtil::dumpEdge(const char* label, int i, TopoDS_Edge e) vEnd.Z(), static_cast(e.Orientation())); double edgeLength = GCPnts_AbscissaPoint::Length(adapt, Precision::Confusion()); - Base::Console().Message(">>>>>>> length: %.3f distance: %.3f ration: %.3f type: %d\n", + Base::Console().Message(">>>>>>> length: %.3f distance: %.3f ratio: %.3f type: %d\n", edgeLength, vStart.Distance(vEnd), edgeLength / vStart.Distance(vEnd), diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 5af01afbd6..45c158a043 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -23,7 +23,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include @@ -300,7 +299,7 @@ void DrawViewDimension::onChanged(const App::Property* prop) } else if (prop == &Type) { FormatSpec.setValue(getDefaultFormatSpec().c_str()); - DimensionType type = static_cast(Type.getValue()); + auto type = static_cast(Type.getValue()); if (type == DimensionType::Angle || type == DimensionType::Angle3Pt) { OverTolerance.setUnit(Base::Unit::Angle); UnderTolerance.setUnit(Base::Unit::Angle); @@ -391,7 +390,7 @@ void DrawViewDimension::onDocumentRestored() setAll3DMeasurement(); } - DimensionType type = static_cast(Type.getValue()); + auto type = static_cast(Type.getValue()); if (type == DimensionType::Angle || type == DimensionType::Angle3Pt) { OverTolerance.setUnit(Base::Unit::Angle); UnderTolerance.setUnit(Base::Unit::Angle); @@ -403,14 +402,14 @@ void DrawViewDimension::handleChangedPropertyType(Base::XMLReader& reader, App::Property* prop) { if (prop == &OverTolerance && strcmp(TypeName, "App::PropertyFloat") == 0) { - App::PropertyFloat v; - v.Restore(reader); - OverTolerance.setValue(v.getValue()); + App::PropertyFloat value; + value.Restore(reader); + OverTolerance.setValue(value.getValue()); } else if (prop == &UnderTolerance && strcmp(TypeName, "App::PropertyFloat") == 0) { - App::PropertyFloat v; - v.Restore(reader); - UnderTolerance.setValue(v.getValue()); + App::PropertyFloat value; + value.Restore(reader); + UnderTolerance.setValue(value.getValue()); } else { TechDraw::DrawView::handleChangedPropertyType(reader, TypeName, prop); @@ -436,7 +435,7 @@ short DrawViewDimension::mustExecute() const { if (!isRestoring()) { if (References2D.isTouched() || References3D.isTouched() || Type.isTouched()) { - return true; + return 1; } } @@ -450,36 +449,19 @@ App::DocumentObjectExecReturn* DrawViewDimension::execute() return new App::DocumentObjectExecReturn("Dimension could not execute"); } + m_referencesCorrect = true; + if (Preferences::autoCorrectDimRefs()) { + m_referencesCorrect = autocorrectReferences(); + } + if (!m_referencesCorrect) { + new App::DocumentObjectExecReturn("Autocorrect failed to fix broken references", this); + } + + // references are good, we can proceed resetLinear(); resetAngular(); resetArc(); - // check if geometry pointed to by references matches the saved version. If - // everything matches, we don't need to correct anything. - std::vector referenceState; - bool refsAreValid = m_corrector->referencesHaveValidGeometry(referenceState); - if (!refsAreValid) { - m_corrector->set3dObjectCache(m_3dObjectCache); - ReferenceVector repairedRefs; - refsAreValid = m_corrector->autocorrectReferences(referenceState, repairedRefs); - if (!refsAreValid) { - // references are broken and we can not fix them - Base::Console().Warning("Autocorrect failed to fix references for %s\n", - getNameInDocument()); - m_referencesCorrect = false; - return new App::DocumentObjectExecReturn("Autocorrect failed to fix broken references", - this); - } - if (repairedRefs.front().is3d()) { - setReferences3d(repairedRefs); - } - else { - setReferences2d(repairedRefs); - } - } - // references are good, we can proceed - m_referencesCorrect = true; - // we have either or both valid References3D and References2D ReferenceVector references = getEffectiveReferences(); @@ -498,11 +480,8 @@ App::DocumentObjectExecReturn* DrawViewDimension::execute() } m_hasGeometry = true; } - else if (Type.isValue("Radius")) { - m_arcPoints = getArcParameters(references); - m_hasGeometry = true; - } - else if (Type.isValue("Diameter")) { + else if (Type.isValue("Radius") || + Type.isValue("Diameter") ) { m_arcPoints = getArcParameters(references); m_hasGeometry = true; } @@ -533,17 +512,21 @@ bool DrawViewDimension::okToProceed() } DrawViewPart* dvp = getViewPart(); if (!dvp) { + // TODO: translate these messages + // this case is probably temporary during restore + // Base::Console().Message("DVD::okToProceed - no view for dimension\n"); return false; } - if (!has2DReferences() && !has3DReferences()) { + if (!(has2DReferences() || has3DReferences())) { // no references, can't do anything - Base::Console().Warning("Dimension object has no valid references\n"); + Base::Console().Warning("DVD::okToProceed - Dimension object has no valid references\n"); return false; } if (!getViewPart()->hasGeometry()) { // can't do anything until Source has geometry + Base::Console().Warning("DVD::okToProceed - Dimension object has no geometry\n"); return false; } @@ -556,6 +539,34 @@ bool DrawViewDimension::okToProceed() return validateReferenceForm(); } +//! check if geometry pointed to by references matches the saved version. If +//! everything matches, we don't need to correct anything. +bool DrawViewDimension::autocorrectReferences() +{ + // Base::Console().Message("DVD::autocorrectReferences()\n"); + std::vector referenceState; + bool refsAreValid = m_corrector->referencesHaveValidGeometry(referenceState); + if (!refsAreValid) { + m_corrector->set3dObjectCache(m_3dObjectCache); + ReferenceVector repairedRefs; + refsAreValid = m_corrector->autocorrectReferences(referenceState, repairedRefs); + if (!refsAreValid) { + // references are broken and we can not fix them + Base::Console().Warning("Autocorrect failed to fix references for %s\n", + getNameInDocument()); + return false; + + } + if (repairedRefs.front().is3d()) { + setReferences3d(repairedRefs); + } + else { + setReferences2d(repairedRefs); + } + } + return true; +} + bool DrawViewDimension::isMultiValueSchema() const { return m_formatter->isMultiValueSchema(); @@ -596,7 +607,7 @@ std::string DrawViewDimension::getFormattedDimensionValue(int partial) return m_formatter->getFormattedDimensionValue(partial); } -QStringList DrawViewDimension::getPrefixSuffixSpec(QString fSpec) +QStringList DrawViewDimension::getPrefixSuffixSpec(const QString &fSpec) { return m_formatter->getPrefixSuffixSpec(fSpec); } @@ -605,6 +616,7 @@ QStringList DrawViewDimension::getPrefixSuffixSpec(QString fSpec) double DrawViewDimension::getDimValue() { // Base::Console().Message("DVD::getDimValue()\n"); + constexpr double CircleDegrees{360.0}; double result = 0.0; if (!has2DReferences() && !has3DReferences()) { // nothing to measure @@ -625,21 +637,7 @@ double DrawViewDimension::getDimValue() getNameInDocument()); return result; } - if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) { - result = measurement->length(); - } - else if (Type.isValue("Radius")) { - result = measurement->radius(); - } - else if (Type.isValue("Diameter")) { - result = 2.0 * measurement->radius(); - } - else if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) { - result = measurement->angle(); - } - else { // tarfu - throw Base::ValueError("getDimValue() - Unknown Dimension Type (3)"); - } + result = getTrueDimValue(); } else { // Projected Values @@ -648,59 +646,13 @@ double DrawViewDimension::getDimValue() getNameInDocument()); return result; } - if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) { - pointPair pts = getLinearPoints(); - auto dbv = dynamic_cast(getViewPart()); - if (dbv) { - // raw pts from view are inverted Y, so we need to un-invert them before mapping - // raw pts are scaled, so we need to unscale them for mapPoint2dFromView - // then rescale them for the distance calculation below - // centers are right side up - // if both points are on the expanded side of the last (rightmost/upmost) break - // then we should not move the points. - // - pts.invertY(); - pts.scale(1.0 / getViewPart()->getScale()); - pts.first(dbv->mapPoint2dFromView(pts.first())); - pts.second(dbv->mapPoint2dFromView(pts.second())); - pts.invertY(); - pts.scale(getViewPart()->getScale()); - } - Base::Vector3d dimVec = pts.first() - pts.second(); - if (Type.isValue("Distance")) { - result = dimVec.Length() / getViewPart()->getScale(); - } - else if (Type.isValue("DistanceX")) { - result = fabs(dimVec.x) / getViewPart()->getScale(); - } - else { - result = fabs(dimVec.y) / getViewPart()->getScale(); - } - } - else if (Type.isValue("Radius")) { - arcPoints pts = m_arcPoints; - result = - pts.radius / getViewPart()->getScale(); // Projected BaseGeom is scaled for drawing - } - else if (Type.isValue("Diameter")) { - arcPoints pts = m_arcPoints; - result = (pts.radius * 2.0) - / getViewPart()->getScale(); // Projected BaseGeom is scaled for drawing - } - else if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) { // same as case "Angle"? - anglePoints pts = m_anglePoints; - Base::Vector3d vertex = pts.vertex(); - Base::Vector3d leg0 = pts.first() - vertex; - Base::Vector3d leg1 = pts.second() - vertex; - double legAngle = leg0.GetAngle(leg1) * 180.0 / M_PI; - result = legAngle; - } + result = getProjectedDimValue(); } result = fabs(result); if (Inverted.getValue()) { if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) { - result = 360 - result; + result = CircleDegrees - result; } else { result = -result; @@ -709,6 +661,88 @@ double DrawViewDimension::getDimValue() return result; } +//! retrieve the dimension value for "true" dimensions. The returned value is in internal units (mm). +double DrawViewDimension::getTrueDimValue() const +{ + // Base::Console().Message("DVD::getTrueDimValue()\n"); + double result = 0.0; + + if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) { + result = measurement->length(); + } + else if (Type.isValue("Radius")) { + result = measurement->radius(); + } + else if (Type.isValue("Diameter")) { + result = 2.0 * measurement->radius(); + } + else if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) { + result = measurement->angle(); + } + else { // tarfu + throw Base::ValueError("getDimValue() - Unknown Dimension Type (3)"); + } + return result; +} + +//! retrieve the dimension value for "projected" (2d) dimensions. The returned value is in internal units (mm). +double DrawViewDimension::getProjectedDimValue() const +{ + // Base::Console().Message("DVD::getProjectedDimValue()\n"); + double result = 0.0; + + if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) { + pointPair pts = getLinearPoints(); + auto dbv = dynamic_cast(getViewPart()); + if (dbv) { + // raw pts from view are inverted Y, so we need to un-invert them before mapping + // raw pts are scaled, so we need to unscale them for mapPoint2dFromView + // then rescale them for the distance calculation below + // centers are right side up + // if both points are on the expanded side of the last (rightmost/upmost) break + // then we should not move the points. + // + pts.invertY(); + pts.scale(1.0 / getViewPart()->getScale()); + pts.first(dbv->mapPoint2dFromView(pts.first())); + pts.second(dbv->mapPoint2dFromView(pts.second())); + pts.invertY(); + pts.scale(getViewPart()->getScale()); + } + Base::Vector3d dimVec = pts.first() - pts.second(); + if (Type.isValue("Distance")) { + result = dimVec.Length() / getViewPart()->getScale(); + } + else if (Type.isValue("DistanceX")) { + result = fabs(dimVec.x) / getViewPart()->getScale(); + } + else { + result = fabs(dimVec.y) / getViewPart()->getScale(); + } + } + else if (Type.isValue("Radius")) { + arcPoints pts = m_arcPoints; + result = + pts.radius / getViewPart()->getScale(); // Projected BaseGeom is scaled for drawing + } + else if (Type.isValue("Diameter")) { + arcPoints pts = m_arcPoints; + result = (pts.radius * 2.0) + / getViewPart()->getScale(); // Projected BaseGeom is scaled for drawing + } + else if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) { // same as case "Angle"? + anglePoints pts = m_anglePoints; + Base::Vector3d vertex = pts.vertex(); + Base::Vector3d leg0 = pts.first() - vertex; + Base::Vector3d leg1 = pts.second() - vertex; + double legAngle = Base::toDegrees(leg0.GetAngle(leg1)); + result = legAngle; + } + + return result; +} + + pointPair DrawViewDimension::getPointsOneEdge(ReferenceVector references) { // Base::Console().Message("DVD::getPointsOneEdge()\n"); @@ -730,12 +764,12 @@ pointPair DrawViewDimension::getPointsOneEdge(ReferenceVector references) throw Base::RuntimeError(ssMessage.str()); } TechDraw::GenericPtr generic = std::static_pointer_cast(geom); + // these points are from 2d geometry, so they are scaled and rotated return {generic->points[0], generic->points[1]}; } // this is a 3d object // get the endpoints of the edge in the DVP's coordinates - Base::Vector3d edgeEnd0, edgeEnd1; TopoDS_Shape geometry = references.front().getGeometry(); if (geometry.IsNull() || geometry.ShapeType() != TopAbs_EDGE) { throw Base::RuntimeError("Geometry for dimension reference is null."); @@ -845,7 +879,8 @@ pointPair DrawViewDimension::getPointsEdgeVert(ReferenceVector references) } // get curve from edge - double start, end; // curve parameters + double start{0.0}; // curve parameters + double end{0.0}; // curve parameters const Handle(Geom_Surface) hplane = new Geom_Plane(gp_Ax3()); auto const occCurve = BRep_Tool::CurveOnPlane(edge->getOCCEdge(), hplane, TopLoc_Location(), start, end); @@ -860,10 +895,8 @@ pointPair DrawViewDimension::getPointsEdgeVert(ReferenceVector references) result.setExtensionLine(closestPoints(edge->getOCCEdge(), vertex->getOCCVertex())); return result; } - else { // unable to project return closestPoints(edge->getOCCEdge(), vertex->getOCCVertex()); - } } // this is a 3d object @@ -974,8 +1007,8 @@ arcPoints DrawViewDimension::arcPointsFromBaseGeom(TechDraw::BaseGeomPtr base) else if (base && base->getGeomType() == TechDraw::GeomType::BSPLINE) { TechDraw::BSplinePtr spline = std::static_pointer_cast(base); if (spline->isCircle()) { - bool arc; - double rad; + bool arc{false}; + double rad{0}; Base::Vector3d center; // bool circ = GeometryUtils::getCircleParms(spline->getOCCEdge(), rad, center, arc); @@ -1141,7 +1174,8 @@ anglePoints DrawViewDimension::getAnglePointsTwoEdges(ReferenceVector references TechDraw::GenericPtr generic0 = std::static_pointer_cast(geom0); TechDraw::GenericPtr generic1 = std::static_pointer_cast(geom1); Base::Vector3d apex = generic0->apparentInter(generic1); - Base::Vector3d farPoint0, farPoint1; + Base::Vector3d farPoint0; + Base::Vector3d farPoint1; // pick the end of generic0 farthest from the apex if ((generic0->getStartPoint() - apex).Length() > (generic0->getEndPoint() - apex).Length()) { @@ -1375,7 +1409,8 @@ int DrawViewDimension::getRefType() const int DrawViewDimension::getRefTypeSubElements(const std::vector& subElements) { int refType = invalidRef; - int refEdges = 0, refVertices = 0; + int refEdges{0}; + int refVertices{0}; for (const auto& se : subElements) { if (DrawUtil::getGeomTypeFromName(se) == "Vertex") { @@ -1408,7 +1443,7 @@ int DrawViewDimension::getRefTypeSubElements(const std::vector& sub //! validate 2D references - only checks if the target exists bool DrawViewDimension::checkReferences2D() const { - // Base::Console().Message("DVD::checkReferences2d() - %s\n", getNameInDocument()); + // Base::Console().Message("DVD::checkReferences2d() - %s\n", getNameInDocument()); const std::vector& objects = References2D.getValues(); if (objects.empty()) { return false; @@ -1425,21 +1460,21 @@ bool DrawViewDimension::checkReferences2D() const return true; } - for (auto& s : subElements) { - if (s.empty()) { + for (auto& sub : subElements) { + if (sub.empty()) { return false; } - int idx = DrawUtil::getIndexFromName(s); - if (DrawUtil::getGeomTypeFromName(s) == "Edge") { + int idx = DrawUtil::getIndexFromName(sub); + if (DrawUtil::getGeomTypeFromName(sub) == "Edge") { TechDraw::BaseGeomPtr geom = getViewPart()->getGeomByIndex(idx); if (!geom) { return false; } } - else if (DrawUtil::getGeomTypeFromName(s) == "Vertex") { - TechDraw::VertexPtr v = getViewPart()->getProjVertexByIndex(idx); - if (!v) { + else if (DrawUtil::getGeomTypeFromName(sub) == "Vertex") { + TechDraw::VertexPtr vert = getViewPart()->getProjVertexByIndex(idx); + if (!vert) { return false; } } @@ -1456,13 +1491,12 @@ bool DrawViewDimension::hasBroken3dReferences() const const std::vector& objects = References2D.getValues(); const std::vector& subElements = References2D.getSubValues(); - if (objects.size() == 1 && objects3d.empty() && subElements.empty()) { - // we have the reference to the View, but no 2d subelements or 3d objects - // this means that the 3d references have been nulled out due to - // object deletion and the reference will need to be rebuilt. - return true; - } - return false; + // if we have the reference to the View, but no 2d subelements or 3d objects + // this means that the 3d references have been nulled out due to + // object deletion and the reference will need to be rebuilt. + return (objects.size() == 1 && + objects3d.empty() && + subElements.empty()); } @@ -1477,28 +1511,20 @@ void DrawViewDimension::updateSavedGeometry() } std::vector newGeometry; const std::vector oldGeometry = SavedGeometry.getValues(); - // need to clean up old geometry objects here? + // need to clean up old saved geometry objects here? - size_t iOldGeom(0); for (auto& entry : references) { if (entry.getSubName().empty()) { // view only reference has no geometry. continue; } if (entry.hasGeometry()) { - newGeometry.push_back(entry.asTopoShape()); + newGeometry.push_back(entry.asCanonicalTopoShape()); } else { - // use old geometry entry? null shape? have to put something in the vector - // so SavedGeometry and references stay in sync. - if (iOldGeom < oldGeometry.size()) { - newGeometry.push_back(oldGeometry.at(iOldGeom)); - } - else { + // have to put something in the vector so SavedGeometry and references stay in sync. newGeometry.push_back(Part::TopoShape()); - } } - iOldGeom++; } if (!newGeometry.empty()) { SavedGeometry.setValues(newGeometry); @@ -1511,35 +1537,34 @@ void DrawViewDimension::updateSavedGeometry() std::vector DrawViewDimension::getEdges(const TopoShape& inShape) { std::vector ret; - TopTools_IndexedMapOfShape M; + TopTools_IndexedMapOfShape shapeMap; TopExp_Explorer Ex(inShape.getShape(), TopAbs_EDGE); while (Ex.More()) { - M.Add(Ex.Current()); + shapeMap.Add(Ex.Current()); Ex.Next(); } - for (Standard_Integer k = 1; k <= M.Extent(); k++) { - const TopoDS_Shape& shape = M(k); + for (Standard_Integer k = 1; k <= shapeMap.Extent(); k++) { + const TopoDS_Shape& shape = shapeMap(k); ret.push_back(TopoShape(shape)); } return ret; } - // based on Part::TopoShapePyImp::getShapes std::vector DrawViewDimension::getVertexes(const TopoShape& inShape) { std::vector ret; - TopTools_IndexedMapOfShape M; + TopTools_IndexedMapOfShape shapeMap; TopExp_Explorer Ex(inShape.getShape(), TopAbs_VERTEX); while (Ex.More()) { - M.Add(Ex.Current()); + shapeMap.Add(Ex.Current()); Ex.Next(); } - for (Standard_Integer k = 1; k <= M.Extent(); k++) { - const TopoDS_Shape& shape = M(k); + for (Standard_Integer k = 1; k <= shapeMap.Extent(); k++) { + const TopoDS_Shape& shape = shapeMap(k); ret.push_back(TopoShape(shape)); } @@ -1555,38 +1580,38 @@ pointPair DrawViewDimension::closestPoints(TopoDS_Shape s1, TopoDS_Shape s2) con } int count = extss.NbSolution(); if (count != 0) { - gp_Pnt p = extss.PointOnShape1(1); - result.first(Base::Vector3d(p.X(), p.Y(), p.Z())); - p = extss.PointOnShape2(1); - result.second(Base::Vector3d(p.X(), p.Y(), p.Z())); + gp_Pnt point = extss.PointOnShape1(1); + result.first(Base::Vector3d(point.X(), point.Y(), point.Z())); + point = extss.PointOnShape2(1); + result.second(Base::Vector3d(point.X(), point.Y(), point.Z())); } // TODO: else { explode } return result; } // set the reference property from a reference vector -void DrawViewDimension::setReferences2d(ReferenceVector refs) +void DrawViewDimension::setReferences2d(ReferenceVector refsAll) { - // Base::Console().Message("DVD::setReferences2d(%d)\n", refs.size()); + // Base::Console().Message("DVD::setReferences2d(%d)\n", refs.size()); std::vector objects; std::vector subNames; if (objects.size() != subNames.size()) { throw Base::IndexError("DVD::setReferences2d - objects and subNames do not match."); } - for (size_t iRef = 0; iRef < refs.size(); iRef++) { - objects.push_back(refs.at(iRef).getObject()); - subNames.push_back(refs.at(iRef).getSubName()); + for (auto& ref : refsAll) { + objects.push_back(ref.getObject()); + subNames.push_back(ref.getSubName()); } References2D.setValues(objects, subNames); } // set the reference property from a reference vector -void DrawViewDimension::setReferences3d(ReferenceVector refs) +void DrawViewDimension::setReferences3d(ReferenceVector refsAll) { // Base::Console().Message("DVD::setReferences3d()\n"); - if (refs.empty() && !References3D.getValues().empty()) { + if (refsAll.empty() && !References3D.getValues().empty()) { // clear the property of any old links References3D.setValue(nullptr, nullptr); return; @@ -1597,17 +1622,17 @@ void DrawViewDimension::setReferences3d(ReferenceVector refs) throw Base::IndexError("DVD::setReferences3d - objects and subNames do not match."); } - for (size_t iRef = 0; iRef < refs.size(); iRef++) { - objects.push_back(refs.at(iRef).getObject()); - subNames.push_back(refs.at(iRef).getSubName()); + for (auto& ref : refsAll) { + objects.push_back(ref.getObject()); + subNames.push_back(ref.getSubName()); // cache the referenced object - m_3dObjectCache.insert(refs.at(iRef).getObject()->getNameInDocument()); + m_3dObjectCache.insert(ref.getObject()->getNameInDocument()); // cache the parent object if available. Ideally, we would handle deletion // of a reference object in a slot for DocumentObject::signalDeletedObject, // but by the time we get the signal the document will have severed any links // between our object and its parents. So we need to cache the parent here while // we still have the link - App::DocumentObject* firstParent = refs.at(iRef).getObject()->getFirstParent(); + App::DocumentObject* firstParent = ref.getObject()->getFirstParent(); if (firstParent) { m_3dObjectCache.insert(firstParent->getNameInDocument()); } @@ -1619,22 +1644,22 @@ void DrawViewDimension::setReferences3d(ReferenceVector refs) //! add Dimension 3D references to measurement void DrawViewDimension::setAll3DMeasurement() { - // Base::Console().Message("DVD::setAll3dMeasurement()\n"); + // Base::Console().Message("DVD::setAll3dMeasurement()\n"); measurement->clear(); const std::vector& Objs = References3D.getValues(); const std::vector& Subs = References3D.getSubValues(); int end = Objs.size(); - int i = 0; - for (; i < end; i++) { - static_cast(measurement->addReference3D(Objs.at(i), Subs.at(i))); + int iObject = 0; + for (; iObject < end; iObject++) { + static_cast(measurement->addReference3D(Objs.at(iObject), Subs.at(iObject))); // cache the referenced object - m_3dObjectCache.insert(Objs.at(i)->getNameInDocument()); + m_3dObjectCache.insert(Objs.at(iObject)->getNameInDocument()); // cache the parent object if available. Ideally, we would handle deletion // of a reference object in a slot for DocumentObject::signalDeletedObject, // but by the time we get the signal the document will have severed any links // between our object and its parents. So we need to cache the parent here while // we still have the link - App::DocumentObject* firstParent = Objs.at(i)->getFirstParent(); + App::DocumentObject* firstParent = Objs.at(iObject)->getFirstParent(); if (firstParent) { m_3dObjectCache.insert(firstParent->getNameInDocument()); } @@ -1645,6 +1670,7 @@ void DrawViewDimension::setAll3DMeasurement() //! dimension. bool DrawViewDimension::validateReferenceForm() const { + // Base::Console().Message("DVD::validateReferenceForm()\n"); // we have either or both valid References3D and References2D ReferenceVector references = getEffectiveReferences(); if (references.empty()) { @@ -1657,89 +1683,72 @@ bool DrawViewDimension::validateReferenceForm() const return false; } std::string subGeom = DrawUtil::getGeomTypeFromName(references.front().getSubName()); - if (subGeom != "Edge") { - return false; - } - return true; + return subGeom == "Edge"; } - else if (getRefType() == twoEdge) { + if (getRefType() == twoEdge) { if (references.size() != 2) { return false; } std::string subGeom0 = DrawUtil::getGeomTypeFromName(references.front().getSubName()); std::string subGeom1 = DrawUtil::getGeomTypeFromName(references.back().getSubName()); - if (subGeom0 != "Edge" || subGeom1 != "Edge") { - return false; - } - return true; + return (subGeom0 == "Edge" && subGeom1 == "Edge"); } - else if (getRefType() == twoVertex) { + + if (getRefType() == twoVertex) { if (references.size() != 2) { return false; } std::string subGeom0 = DrawUtil::getGeomTypeFromName(references.front().getSubName()); std::string subGeom1 = DrawUtil::getGeomTypeFromName(references.back().getSubName()); - if (subGeom0 != "Vertex" || subGeom1 != "Vertex") { - return false; - } - return true; + return (subGeom0 == "Vertex" && subGeom1 == "Vertex"); } - else if (getRefType() == vertexEdge) { + + if (getRefType() == vertexEdge) { if (references.size() != 2) { return false; } std::string subGeom0 = DrawUtil::getGeomTypeFromName(references.front().getSubName()); std::string subGeom1 = DrawUtil::getGeomTypeFromName(references.back().getSubName()); - if ( (subGeom0 == "Vertex" && subGeom1 == "Edge") || - (subGeom0 == "Edge" && subGeom1 == "Vertex") ) { - return true; - } - return false; + return ( (subGeom0 == "Vertex" && subGeom1 == "Edge") || + (subGeom0 == "Edge" && subGeom1 == "Vertex") ); } } - else if (Type.isValue("Radius")) { + + if (Type.isValue("Radius")) { if (references.size() != 1) { return false; } std::string subGeom = DrawUtil::getGeomTypeFromName(references.front().getSubName()); - if (subGeom != "Edge") { - return false; - } - return true; + return subGeom == "Edge"; } - else if (Type.isValue("Diameter")) { + + if (Type.isValue("Diameter")) { if (references.size() != 1) { return false; } std::string subGeom = DrawUtil::getGeomTypeFromName(references.front().getSubName()); - if (subGeom != "Edge") { - return false; - } - return true; + return (subGeom == "Edge"); } - else if (Type.isValue("Angle")) { + + if (Type.isValue("Angle")) { if (references.size() != 2) { return false; } std::string subGeom0 = DrawUtil::getGeomTypeFromName(references.front().getSubName()); std::string subGeom1 = DrawUtil::getGeomTypeFromName(references.back().getSubName()); - if (subGeom0 != "Edge" || subGeom1 != "Edge") { - return false; - } - return true; + return (subGeom0 == "Edge" && subGeom1 == "Edge"); } - else if (Type.isValue("Angle3Pt")) { + + if (Type.isValue("Angle3Pt")) { if (references.size() != 3) { return false; } std::string subGeom0 = DrawUtil::getGeomTypeFromName(references.at(0).getSubName()); std::string subGeom1 = DrawUtil::getGeomTypeFromName(references.at(1).getSubName()); std::string subGeom2 = DrawUtil::getGeomTypeFromName(references.at(2).getSubName()); - if (subGeom0 != "Vertex" || subGeom1 != "Vertex" || subGeom2 != "Vertex") { - return false; - } - return true; + return (subGeom0 == "Vertex" && subGeom1 == "Vertex" && subGeom2 == "Vertex"); } + return false; } @@ -1899,11 +1908,9 @@ bool DrawViewDimension::has3DReferences() const // has arbitrary or nonzero tolerance bool DrawViewDimension::hasOverUnderTolerance() const { - if (ArbitraryTolerances.getValue() || !DrawUtil::fpCompare(OverTolerance.getValue(), 0.0) - || !DrawUtil::fpCompare(UnderTolerance.getValue(), 0.0)) { - return true; - } - return false; + return (ArbitraryTolerances.getValue() || + !DrawUtil::fpCompare(OverTolerance.getValue(), 0.0) || + !DrawUtil::fpCompare(UnderTolerance.getValue(), 0.0)); } bool DrawViewDimension::showUnits() const @@ -1921,7 +1928,8 @@ std::string DrawViewDimension::getPrefixForDimType() const if (Type.isValue("Radius")) { return "R"; } - else if (Type.isValue("Diameter")) { + + if (Type.isValue("Diameter")) { return std::string(Preferences::getPreferenceGroup("Dimensions") ->GetASCII("DiameterSymbol", "\xe2\x8c\x80")); // Diameter symbol } @@ -1936,11 +1944,9 @@ std::string DrawViewDimension::getDefaultFormatSpec(bool isToleranceFormat) cons bool DrawViewDimension::isExtentDim() const { + constexpr int DimExtentLength{9}; std::string name(getNameInDocument()); - if (name.substr(0, 9) == "DimExtent") { - return true; - } - return false; + return (name.substr(0, DimExtentLength) == "DimExtent"); } diff --git a/src/Mod/TechDraw/App/DrawViewDimension.h b/src/Mod/TechDraw/App/DrawViewDimension.h index babc4de683..c7d687ab2b 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.h +++ b/src/Mod/TechDraw/App/DrawViewDimension.h @@ -128,7 +128,10 @@ public: virtual bool haveTolerance(); virtual double getDimValue(); - QStringList getPrefixSuffixSpec(QString fSpec); + virtual double getTrueDimValue() const; + virtual double getProjectedDimValue() const; + + QStringList getPrefixSuffixSpec(const QString& fSpec); virtual DrawViewPart* getViewPart() const; QRectF getRect() const override @@ -238,6 +241,7 @@ protected: void updateSavedGeometry(); bool validateReferenceForm() const; + bool autocorrectReferences(); private: static const char* TypeEnums[]; diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index a1d129129f..d6c93534d8 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -96,14 +96,16 @@ using DU = DrawUtil; PROPERTY_SOURCE_WITH_EXTENSIONS(TechDraw::DrawViewPart, TechDraw::DrawView) -DrawViewPart::DrawViewPart(void) - : geometryObject(nullptr), m_tempGeometryObject(nullptr), m_waitingForFaces(false), +DrawViewPart::DrawViewPart() + : geometryObject(nullptr), + m_tempGeometryObject(nullptr), + m_handleFaces(false), + nowUnsetting(false), + m_waitingForFaces(false), m_waitingForHlr(false) { static const char* group = "Projection"; static const char* sgroup = "HLR Parameters"; - nowUnsetting = false; - m_handleFaces = false; CosmeticExtension::initExtension(this); @@ -203,14 +205,14 @@ std::vector DrawViewPart::getAllSources() const //! pick vertex objects out of the Source properties and //! add them directly to the geometry without going through HLR -void DrawViewPart::addPoints(void) +void DrawViewPart::addPoints() { // Base::Console().Message("DVP::addPoints()\n"); // get all the 2d shapes in the sources, then pick through them for vertices. - std::vector shapes = ShapeExtractor::getShapes2d(getAllSources()); - for (auto& s : shapes) { - if (s.ShapeType() == TopAbs_VERTEX) { - gp_Pnt gp = BRep_Tool::Pnt(TopoDS::Vertex(s)); + std::vector shapesAll = ShapeExtractor::getShapes2d(getAllSources()); + for (auto& shape : shapesAll) { + if (shape.ShapeType() == TopAbs_VERTEX) { + gp_Pnt gp = BRep_Tool::Pnt(TopoDS::Vertex(shape)); Base::Vector3d vp(gp.X(), gp.Y(), gp.Z()); vp = vp - m_saveCentroid; //need to offset the point to match the big projection @@ -221,9 +223,9 @@ void DrawViewPart::addPoints(void) } } -App::DocumentObjectExecReturn* DrawViewPart::execute(void) +App::DocumentObjectExecReturn* DrawViewPart::execute() { - // Base::Console().Message("DVP::execute() - %s\n", getNameInDocument()); + // Base::Console().Message("DVP::execute() - %s\n", getNameInDocument()); if (!keepUpdated()) { return DrawView::execute(); } @@ -375,7 +377,7 @@ TechDraw::GeometryObjectPtr DrawViewPart::buildGeometryObject(TopoDS_Shape& shap } //! continue processing after hlr thread completes -void DrawViewPart::onHlrFinished(void) +void DrawViewPart::onHlrFinished() { // Base::Console().Message("DVP::onHlrFinished() - %s\n", getNameInDocument()); @@ -423,9 +425,9 @@ void DrawViewPart::onHlrFinished(void) } //! run any tasks that need to been done after geometry is available -void DrawViewPart::postHlrTasks(void) +void DrawViewPart::postHlrTasks() { - // Base::Console().Message("DVP::postHlrTasks() - %s\n", getNameInDocument()); + // Base::Console().Message("DVP::postHlrTasks() - %s\n", getNameInDocument()); //add geometry that doesn't come from HLR addCosmeticVertexesToGeom(); addCosmeticEdgesToGeom(); @@ -434,15 +436,15 @@ void DrawViewPart::postHlrTasks(void) //balloons need to be recomputed here because their //references will be invalid until the geometry exists - std::vector bals = getBalloons(); - for (auto& b : bals) { - b->recomputeFeature(); + std::vector balloonsAll = getBalloons(); + for (auto& balloon : balloonsAll) { + balloon->recomputeFeature(); } // Dimensions need to be recomputed now if face finding is not going to take place. if (!handleFaces() || CoarseView.getValue()) { - std::vector dims = getDimensions(); - for (auto& d : dims) { - d->recomputeFeature(); + std::vector dimsAll = getDimensions(); + for (auto& dim : dimsAll) { + dim->recomputeFeature(); } } @@ -460,16 +462,17 @@ void DrawViewPart::postHlrTasks(void) } // Run any tasks that need to be done after faces are available -void DrawViewPart::postFaceExtractionTasks(void) +void DrawViewPart::postFaceExtractionTasks() { + // Base::Console().Message("DVP::postFaceExtractionTasks() - %s\n", getNameInDocument()); // Some centerlines depend on faces so we could not add CL geometry before now addCenterLinesToGeom(); // Dimensions need to be recomputed because their references will be invalid // until all the geometry (including centerlines dependent on faces) exists. - std::vector dims = getDimensions(); - for (auto& d : dims) { - d->recomputeFeature(); + std::vector dimsAll = getDimensions(); + for (auto& dim : dimsAll) { + dim->recomputeFeature(); } requestPaint(); @@ -529,10 +532,10 @@ void DrawViewPart::findFacesNew(const std::vector &goEdges) geometryObject->clearFaceGeom(); std::vector closedWires; - for (auto& e : closedEdges) { - BRepBuilderAPI_MakeWire mkWire(e); - TopoDS_Wire w = mkWire.Wire(); - closedWires.push_back(w); + for (auto& edge : closedEdges) { + BRepBuilderAPI_MakeWire mkWire(edge); + TopoDS_Wire wire = mkWire.Wire(); + closedWires.push_back(wire); } if (!closedWires.empty()) { sortedWires.insert(sortedWires.end(), closedWires.begin(), closedWires.end()); @@ -548,7 +551,7 @@ void DrawViewPart::findFacesNew(const std::vector &goEdges) } else { constexpr double minWireArea = 0.000001;//arbitrary very small face size - std::vector::iterator itWire = sortedWires.begin(); + auto itWire = sortedWires.begin(); for (; itWire != sortedWires.end(); itWire++) { if (!BRep_Tool::IsClosed(*itWire)) { continue;//can not make a face from open wire @@ -559,17 +562,18 @@ void DrawViewPart::findFacesNew(const std::vector &goEdges) continue;//can not make a face from wire with no area } - TechDraw::FacePtr f(std::make_shared()); + TechDraw::FacePtr face(std::make_shared()); const TopoDS_Wire& wire = (*itWire); - f->wires.push_back(new TechDraw::Wire(wire)); + face->wires.push_back(new TechDraw::Wire(wire)); if (geometryObject) { - geometryObject->addFaceGeom(f); + geometryObject->addFaceGeom(face); } } } } -// original face finding method +// original face finding method. This is retained only to produce the same face geometry in older +// documents. void DrawViewPart::findFacesOld(const std::vector &goEdges) { //make a copy of the input edges so the loose tolerances of face finding are @@ -685,7 +689,7 @@ void DrawViewPart::findFacesOld(const std::vector &goEdges) } //continue processing after extractFaces thread completes -void DrawViewPart::onFacesFinished(void) +void DrawViewPart::onFacesFinished() { // Base::Console().Message("DVP::onFacesFinished() - %s\n", getNameInDocument()); waitingForFaces(false); @@ -1025,24 +1029,15 @@ bool DrawViewPart::waitingForResult() const return false; } -bool DrawViewPart::hasGeometry(void) const +bool DrawViewPart::hasGeometry() const { if (!geometryObject) { return false; } - if (waitingForHlr()) { - return false; - } const std::vector& verts = getVertexGeometry(); const std::vector& edges = getEdgeGeometry(); - if (verts.empty() && edges.empty()) { - return false; - } - else { - return true; - } - return false; + return !(verts.empty() && edges.empty()); } //convert a vector in local XY coords into a coordinate system in global @@ -1165,7 +1160,7 @@ bool DrawViewPart::handleFaces() return Preferences::getPreferenceGroup("General")->GetBool("HandleFaces", true); } -bool DrawViewPart::newFaceFinder(void) +bool DrawViewPart::newFaceFinder() { return Preferences::getPreferenceGroup("General")->GetBool("NewFaceFinder", false); } @@ -1442,6 +1437,7 @@ void DrawViewPart::removeReferenceVertex(std::string tag) resetReferenceVerts(); } +//! remove reference vertexes from the view geometry void DrawViewPart::removeAllReferencesFromGeom() { // Base::Console().Message("DVP::removeAllReferencesFromGeom()\n"); diff --git a/src/Mod/TechDraw/App/Geometry.h b/src/Mod/TechDraw/App/Geometry.h index 6243ec5086..759e9d18ed 100644 --- a/src/Mod/TechDraw/App/Geometry.h +++ b/src/Mod/TechDraw/App/Geometry.h @@ -146,7 +146,7 @@ class TechDrawExport BaseGeom : public std::enable_shared_from_this void sourceIndex(int si) { m_sourceIndex = si; } std::string getCosmeticTag() { return cosmeticTag; } void setCosmeticTag(std::string t) { cosmeticTag = t; } - Part::TopoShape asTopoShape(double scale); + Part::TopoShape asTopoShape(double scale = 1.0); virtual double getStartAngle() { return 0.0; } virtual double getEndAngle() { return 0.0; } @@ -391,7 +391,7 @@ class TechDrawExport Vertex bool isReference() { return m_reference; } void isReference(bool state) { m_reference = state; } - Part::TopoShape asTopoShape(double scale); + Part::TopoShape asTopoShape(double scale = 1.0); protected: //Uniqueness diff --git a/src/Mod/TechDraw/App/GeometryMatcher.cpp b/src/Mod/TechDraw/App/GeometryMatcher.cpp index f177b94894..004e195860 100644 --- a/src/Mod/TechDraw/App/GeometryMatcher.cpp +++ b/src/Mod/TechDraw/App/GeometryMatcher.cpp @@ -52,22 +52,20 @@ using DU = DrawUtil; // a set of routines for comparing geometry for equality. -bool GeometryMatcher::compareGeometry(Part::TopoShape shape1, Part::TopoShape shape2) +bool GeometryMatcher::compareGeometry(const Part::TopoShape &shape1, const Part::TopoShape &shape2) { - // Base::Console().Message("GM::compareGeometry()\n"); + // Base::Console().Message("GM::compareGeometry()\n"); if (!Preferences::useExactMatchOnDims()) { return false; } if (shape1.isNull() || shape2.isNull()) { - // Base::Console().Message("GM::compareGeometry - one or more TopoShapes are - // null\n"); + Base::Console().Message("GM::compareGeometry - at least 1 input shape is null (1)\n"); return false; } - TopoDS_Shape geom1 = shape1.getShape(); - TopoDS_Shape geom2 = shape2.getShape(); + const TopoDS_Shape& geom1 = shape1.getShape(); + const TopoDS_Shape& geom2 = shape2.getShape(); if (geom1.IsNull() || geom2.IsNull()) { - // Base::Console().Message("GM::compareGeometry - one or more TopoDS_Shapes are - // null\n"); + Base::Console().Message("GM::compareGeometry - at least 1 input shape is null (2)\n"); return false; } @@ -80,10 +78,9 @@ bool GeometryMatcher::compareGeometry(Part::TopoShape shape1, Part::TopoShape sh return false; } -bool GeometryMatcher::comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2) +bool GeometryMatcher::comparePoints(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2) { // Base::Console().Message("GM::comparePoints()\n"); - if (shape1.ShapeType() != TopAbs_VERTEX || shape2.ShapeType() != TopAbs_VERTEX) { // can not compare these shapes return false; @@ -92,24 +89,18 @@ bool GeometryMatcher::comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2) Base::Vector3d point1 = DU::toVector3d(BRep_Tool::Pnt(vert1)); auto vert2 = TopoDS::Vertex(shape2); Base::Vector3d point2 = DU::toVector3d(BRep_Tool::Pnt(vert2)); - if (point1.IsEqual(point2, EWTOLERANCE)) { - return true; - } - return false; + return point1.IsEqual(point2, EWTOLERANCE); } -bool GeometryMatcher::compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2) +bool GeometryMatcher::compareEdges(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2) { - // Base::Console().Message("GM::compareEdges()\n"); + // Base::Console().Message("GM::compareEdges()\n"); if (shape1.ShapeType() != TopAbs_EDGE || shape2.ShapeType() != TopAbs_EDGE) { - // can not compare these shapes - // Base::Console().Message("GM::compareEdges - shape is not an edge\n"); - return false; + return false; } TopoDS_Edge edge1 = TopoDS::Edge(shape1); TopoDS_Edge edge2 = TopoDS::Edge(shape2); if (edge1.IsNull() || edge2.IsNull()) { - // Base::Console().Message("GM::compareEdges - an input edge is null\n"); return false; } @@ -124,18 +115,14 @@ bool GeometryMatcher::compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2) if (adapt1.IsClosed() && adapt2.IsClosed()) { return compareCircles(edge1, edge2); } - else { - return compareCircleArcs(edge1, edge2); - } + return compareCircleArcs(edge1, edge2); } if (adapt1.GetType() == GeomAbs_Ellipse && adapt2.GetType() == GeomAbs_Ellipse) { if (adapt1.IsClosed() && adapt2.IsClosed()) { return compareEllipses(edge1, edge2); } - else { - return compareEllipseArcs(edge1, edge2); - } + return compareEllipseArcs(edge1, edge2); } if (adapt1.GetType() == GeomAbs_BSplineCurve && adapt2.GetType() == GeomAbs_BSplineCurve) { @@ -146,9 +133,9 @@ bool GeometryMatcher::compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2) return compareDifferent(edge1, edge2); } -bool GeometryMatcher::compareLines(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareLines(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { - // Base::Console().Message("GM::compareLines()\n"); + // Base::Console().Message("GM::compareLines()\n"); // how does the edge that was NOT null in compareEdges become null here? // should not happen, but does! if (edge1.IsNull() || edge2.IsNull()) { @@ -159,19 +146,14 @@ bool GeometryMatcher::compareLines(TopoDS_Edge& edge1, TopoDS_Edge& edge2) auto end1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edge1))); auto start2 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(edge2))); auto end2 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edge2))); - if (start1.IsEqual(start2, EWTOLERANCE) && end1.IsEqual(end2, EWTOLERANCE)) { - // exact match - return true; - } - return false; + return start1.IsEqual(start2, EWTOLERANCE) && end1.IsEqual(end2, EWTOLERANCE); } -bool GeometryMatcher::compareCircles(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareCircles(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { // Base::Console().Message("GM::compareCircles()\n"); // how does the edge that was NOT null in compareEdges become null here? if (edge1.IsNull() || edge2.IsNull()) { - // Base::Console().Message("GM::compareCircles - an input edge is null\n"); return false; } @@ -183,18 +165,13 @@ bool GeometryMatcher::compareCircles(TopoDS_Edge& edge1, TopoDS_Edge& edge2) double radius2 = circle2.Radius(); auto center1 = DU::toVector3d(circle1.Location()); auto center2 = DU::toVector3d(circle2.Location()); - if (DU::fpCompare(radius1, radius2, EWTOLERANCE) && center1.IsEqual(center2, EWTOLERANCE)) { - // exact match - return true; - } - return false; + return DU::fpCompare(radius1, radius2, EWTOLERANCE) && center1.IsEqual(center2, EWTOLERANCE); } -bool GeometryMatcher::compareEllipses(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareEllipses(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { // how does the edge that was NOT null in compareEdges become null here? if (edge1.IsNull() || edge2.IsNull()) { - // Base::Console().Message("GM::compareEllipses - an input edge is null\n"); return false; } @@ -208,21 +185,17 @@ bool GeometryMatcher::compareEllipses(TopoDS_Edge& edge1, TopoDS_Edge& edge2) double minor2 = ellipse2.MinorRadius(); auto center1 = DU::toVector3d(ellipse1.Location()); auto center2 = DU::toVector3d(ellipse2.Location()); - if (DU::fpCompare(major1, major2, EWTOLERANCE) && DU::fpCompare(minor1, minor2, EWTOLERANCE) - && center1.IsEqual(center2, EWTOLERANCE)) { - // exact match - return true; - } - return false; + return (DU::fpCompare(major1, major2, EWTOLERANCE) && + DU::fpCompare(minor1, minor2, EWTOLERANCE) && + center1.IsEqual(center2, EWTOLERANCE)); } // for our purposes, only lines or circles masquerading as bsplines are of interest -bool GeometryMatcher::compareBSplines(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareBSplines(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { // Base::Console().Message("GM::compareBSplines()\n"); // how does the edge that was NOT null in compareEdges become null here? if (edge1.IsNull() || edge2.IsNull()) { - Base::Console().Message("GM::compareBSplines - an input edge is null\n"); return false; } @@ -258,19 +231,19 @@ bool GeometryMatcher::compareBSplines(TopoDS_Edge& edge1, TopoDS_Edge& edge2) } // this is a weak comparison. we should also check center & radius? -bool GeometryMatcher::compareCircleArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareCircleArcs(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { return compareEndPoints(edge1, edge2); } -bool GeometryMatcher::compareEllipseArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareEllipseArcs(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { return compareEndPoints(edge1, edge2); } // this is where we would try to match a bspline against a line or a circle. // not sure how successful this would be. For now, we just say it doesn't match -bool GeometryMatcher::compareDifferent(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareDifferent(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { // Base::Console().Message("GM::compareDifferent()\n"); BRepAdaptor_Curve adapt1(edge1); @@ -278,11 +251,10 @@ bool GeometryMatcher::compareDifferent(TopoDS_Edge& edge1, TopoDS_Edge& edge2) return false; } -bool GeometryMatcher::compareEndPoints(TopoDS_Edge& edge1, TopoDS_Edge& edge2) +bool GeometryMatcher::compareEndPoints(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { // how does the edge that was NOT null in compareEdges become null here? if (edge1.IsNull() || edge2.IsNull()) { - // Base::Console().Message("GM::compareLine - an input edge is null\n"); return false; } @@ -301,9 +273,7 @@ bool GeometryMatcher::compareEndPoints(TopoDS_Edge& edge1, TopoDS_Edge& edge2) props2.SetParameter(pLast2); auto end2 = DU::toVector3d(props2.Value()); - if (begin1.IsEqual(begin2, EWTOLERANCE) && end1.IsEqual(end2, EWTOLERANCE)) { - // exact match - return true; - } - return false; + return (begin1.IsEqual(begin2, EWTOLERANCE) && + end1.IsEqual(end2, EWTOLERANCE)); } + diff --git a/src/Mod/TechDraw/App/GeometryMatcher.h b/src/Mod/TechDraw/App/GeometryMatcher.h index ad81be80d4..00dd3028dc 100644 --- a/src/Mod/TechDraw/App/GeometryMatcher.h +++ b/src/Mod/TechDraw/App/GeometryMatcher.h @@ -39,25 +39,12 @@ namespace TechDraw class TechDrawExport GeometryMatcher { public: - GeometryMatcher() - {} - explicit GeometryMatcher(DrawViewDimension* dim) - { - m_dimension = dim; - } - ~GeometryMatcher() = default; + GeometryMatcher() : + m_dimension(nullptr) {} + explicit GeometryMatcher(DrawViewDimension* dim) : + m_dimension(dim) {} - bool compareGeometry(Part::TopoShape geom1, Part::TopoShape geom2); - bool comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2); - bool compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2); - - bool compareLines(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareCircles(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareEllipses(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareBSplines(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareDifferent(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareCircleArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2); - bool compareEllipseArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2); + bool compareGeometry(const Part::TopoShape& geom1, const Part::TopoShape& geom2); double getPointTolerance() const { @@ -69,7 +56,18 @@ public: } private: - bool compareEndPoints(TopoDS_Edge& edge1, TopoDS_Edge& edge2); + static bool comparePoints(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2); + static bool compareEdges(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2); + + static bool compareLines(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareCircles(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareEllipses(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareBSplines(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareDifferent(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + + static bool compareCircleArcs(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareEllipseArcs(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); + static bool compareEndPoints(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2); DrawViewDimension* m_dimension; double m_pointTolerance {EWTOLERANCE}; diff --git a/src/Mod/TechDraw/App/GeometryObject.cpp b/src/Mod/TechDraw/App/GeometryObject.cpp index dce0009c67..9fa38d9c92 100644 --- a/src/Mod/TechDraw/App/GeometryObject.cpp +++ b/src/Mod/TechDraw/App/GeometryObject.cpp @@ -142,7 +142,6 @@ void GeometryObject::clear() void GeometryObject::projectShape(const TopoDS_Shape& inShape, const gp_Ax2& viewAxis) { -// Base::Console().Message("GO::projectShape()\n"); clear(); Handle(HLRBRep_Algo) brep_hlr; @@ -286,21 +285,6 @@ void GeometryObject::makeTDGeometry() } } -//mirror a shape thru XZ plane for Qt's inverted Y coordinate -TopoDS_Shape ShapeUtils::invertGeometry(const TopoDS_Shape s) -{ - if (s.IsNull()) { - return s; - } - - gp_Trsf mirrorY; - gp_Pnt org(0.0, 0.0, 0.0); - gp_Dir Y(0.0, 1.0, 0.0); - gp_Ax2 mirrorPlane(org, Y); - mirrorY.SetMirror(mirrorPlane); - BRepBuilderAPI_Transform mkTrf(s, mirrorY, true); - return mkTrf.Shape(); -} //!set up a hidden line remover and project a shape with it void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input, const gp_Ax2& viewAxis) diff --git a/src/Mod/TechDraw/App/ShapeUtils.cpp b/src/Mod/TechDraw/App/ShapeUtils.cpp index c0e8d085e1..2ea0b837ee 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.cpp +++ b/src/Mod/TechDraw/App/ShapeUtils.cpp @@ -320,6 +320,48 @@ TopoDS_Shape ShapeUtils::moveShape(const TopoDS_Shape& input, const Base::Vector return transShape; } +//mirror a shape thru XZ plane for Qt's inverted Y coordinate +TopoDS_Shape ShapeUtils::invertGeometry(const TopoDS_Shape s) +{ + if (s.IsNull()) { + return s; + } + + gp_Trsf mirrorY; + gp_Pnt org(0.0, 0.0, 0.0); + gp_Dir Y(0.0, 1.0, 0.0); + gp_Ax2 mirrorPlane(org, Y); + mirrorY.SetMirror(mirrorPlane); + BRepBuilderAPI_Transform mkTrf(s, mirrorY, true); + return mkTrf.Shape(); +} + +//! transforms a shape defined in invertedY (Qt) coordinates into one defined by +//! conventional coordinates +TopoDS_Shape ShapeUtils::fromQt(const TopoDS_Shape& inShape) +{ + gp_Ax3 OXYZ; + gp_Ax3 Qt; + Qt.YReverse(); + gp_Trsf xFromQt; + xFromQt.SetTransformation(Qt, OXYZ); + BRepBuilderAPI_Transform mkTrf(inShape, xFromQt); + return mkTrf.Shape(); +} + +//! transforms a shape defined in conventional coordinates coordinates into one defined by +//! invertedY (Qt) coordinates +TopoDS_Shape ShapeUtils::toQt(const TopoDS_Shape& inShape) +{ + gp_Ax3 OXYZ; + gp_Ax3 Qt; + Qt.YReverse(); + gp_Trsf xFromQt; + xFromQt.SetTransformation(OXYZ, Qt); + BRepBuilderAPI_Transform mkTrf(inShape, xFromQt); + return mkTrf.Shape(); +} + std::pair ShapeUtils::getEdgeEnds(TopoDS_Edge edge) { std::pair result; diff --git a/src/Mod/TechDraw/App/ShapeUtils.h b/src/Mod/TechDraw/App/ShapeUtils.h index e5bf7bca63..dab431248f 100644 --- a/src/Mod/TechDraw/App/ShapeUtils.h +++ b/src/Mod/TechDraw/App/ShapeUtils.h @@ -110,6 +110,9 @@ public: static bool isShapeReallyNull(TopoDS_Shape shape); static bool edgesAreParallel(TopoDS_Edge edge0, TopoDS_Edge edge1); + + static TopoDS_Shape fromQt(const TopoDS_Shape& inShape); + static TopoDS_Shape toQt(const TopoDS_Shape& inShape); }; }