| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <TopoDS_Shape.hxx> |
| |
|
| | #include <App/Document.h> |
| | #include <Base/Console.h> |
| | #include <Base/Tools.h> |
| |
|
| | #include <Mod/Part/App/TopoShape.h> |
| | #include <Mod/Measure/App/ShapeFinder.h> |
| |
|
| | #include "GeometryMatcher.h" |
| | #include "DimensionReferences.h" |
| | #include "DimensionGeometry.h" |
| | #include "DimensionAutoCorrect.h" |
| | #include "DrawUtil.h" |
| | #include "Preferences.h" |
| |
|
| | using namespace TechDraw; |
| | using namespace Measure; |
| | using DU = DrawUtil; |
| |
|
| | |
| | |
| | |
| | |
| | bool DimensionAutoCorrect::referencesHaveValidGeometry(std::vector<bool>& referenceState) const |
| | { |
| | |
| | ReferenceVector refsAll = getDimension()->getEffectiveReferences(); |
| | const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues(); |
| |
|
| | if (savedGeometry.empty() || savedGeometry.size() != refsAll.size()) { |
| | |
| | |
| | referenceState = std::vector<bool>(refsAll.size(), true); |
| | return true; |
| | } |
| |
|
| | bool result {true}; |
| | size_t iRef {0}; |
| | for (auto& entry : refsAll) { |
| | if (entry.hasGeometry()) { |
| | |
| | if (isMatchingGeometry(entry, savedGeometry.at(iRef))) { |
| | referenceState.emplace_back(true); |
| | } |
| | else { |
| | result = false; |
| | referenceState.emplace_back(false); |
| | } |
| | } |
| | else { |
| | result = false; |
| | referenceState.emplace_back(false); |
| | } |
| | iRef++; |
| | } |
| | return result; |
| | } |
| |
|
| | |
| | |
| | |
| | bool DimensionAutoCorrect::autocorrectReferences(std::vector<bool>& referenceState, |
| | ReferenceVector& repairedRefs) const |
| | { |
| | |
| | if (!Preferences::autoCorrectDimRefs()) { |
| | return false; |
| | } |
| |
|
| | bool result {true}; |
| | ReferenceVector refsAll = getDimension()->getEffectiveReferences(); |
| | const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues(); |
| | if (savedGeometry.empty() || savedGeometry.size() != refsAll.size()) { |
| | |
| | |
| | |
| | return true; |
| | } |
| |
|
| | size_t iRef {0}; |
| | for (const auto& state : referenceState) { |
| | if (state) { |
| | |
| | referenceState.at(iRef) = true; |
| | repairedRefs.push_back(refsAll.at(iRef)); |
| | iRef++; |
| | continue; |
| | } |
| |
|
| | const Part::TopoShape& temp = savedGeometry.at(iRef); |
| | if (temp.isNull()) { |
| | result = false; |
| | referenceState.at(iRef) = false; |
| | repairedRefs.push_back(refsAll.at(iRef)); |
| | iRef++; |
| | |
| | continue; |
| | } |
| |
|
| | |
| | |
| | ReferenceEntry fixedRef = refsAll.at(iRef); |
| |
|
| | |
| | bool success = fix1GeomExact(fixedRef, savedGeometry.at(iRef).getShape()); |
| | if (success) { |
| | |
| | referenceState.at(iRef) = true; |
| | repairedRefs.push_back(fixedRef); |
| | iRef++; |
| | continue; |
| | } |
| |
|
| | |
| | success = fix1GeomSimilar(fixedRef, savedGeometry.at(iRef).getShape()); |
| | if (success) { |
| | |
| | referenceState.at(iRef) = true; |
| | repairedRefs.push_back(fixedRef); |
| | iRef++; |
| | continue; |
| | } |
| |
|
| | |
| | result = false; |
| | referenceState.at(iRef) = false; |
| | repairedRefs.push_back(fixedRef); |
| | iRef++; |
| | |
| | } |
| |
|
| | return result; |
| | } |
| |
|
| | |
| | bool DimensionAutoCorrect::fix1GeomExact(ReferenceEntry& refToFix, const TopoDS_Shape &geomToMatch) const |
| | { |
| | |
| | ReferenceEntry fixedRef = refToFix; |
| | Part::TopoShape topoShapeToMatch(geomToMatch); |
| | bool success {false}; |
| | if (refToFix.is3d()) { |
| | if (!refToFix.getObject() && m_3dObjectCache.empty()) { |
| | return false; |
| | } |
| | if (geomToMatch.ShapeType() == TopAbs_VERTEX) { |
| | success = findExactVertex3d(refToFix, topoShapeToMatch); |
| | } |
| | else { |
| | success = findExactEdge3d(refToFix, topoShapeToMatch); |
| | } |
| | } |
| | else { |
| | if (geomToMatch.ShapeType() == TopAbs_VERTEX) { |
| | success = findExactVertex2d(refToFix, topoShapeToMatch); |
| | } |
| | else { |
| | success = findExactEdge2d(refToFix, topoShapeToMatch); |
| | } |
| | } |
| | return success; |
| | } |
| |
|
| |
|
| | |
| | bool DimensionAutoCorrect::fix1GeomSimilar(ReferenceEntry& refToFix, const TopoDS_Shape &geomToMatch) const |
| | { |
| | |
| | Part::TopoShape topoShapeToMatch(geomToMatch); |
| | bool success {false}; |
| | if (refToFix.is3d()) { |
| | if (!refToFix.getObject() && m_3dObjectCache.empty()) { |
| | |
| | return false; |
| | } |
| | if (geomToMatch.ShapeType() == TopAbs_VERTEX) { |
| | success = findSimilarVertex3d(refToFix, topoShapeToMatch); |
| | } |
| | else { |
| | success = findSimilarEdge3d(refToFix, topoShapeToMatch); |
| | } |
| | } |
| | else { |
| | if (geomToMatch.ShapeType() == TopAbs_VERTEX) { |
| | success = findSimilarVertex2d(refToFix, topoShapeToMatch); |
| | } |
| | else { |
| | success = findSimilarEdge2d(refToFix, topoShapeToMatch); |
| | } |
| | } |
| | return success; |
| | } |
| |
|
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findExactVertex2d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | getMatcher()->setPointTolerance(EWTOLERANCE); |
| | auto refObj = refToFix.getObject(); |
| | auto refDvp = dynamic_cast<TechDraw::DrawViewPart*>(refObj); |
| | if (refDvp) { |
| | ReferenceEntry fixedRef = searchViewForVert(refDvp, refGeom); |
| | if (fixedRef.getObject()) { |
| | refToFix = fixedRef; |
| | return true; |
| | } |
| | } |
| | |
| | return false; |
| | } |
| |
|
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findExactEdge2d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const |
| | { |
| | |
| | auto refObj = refToFix.getObject(); |
| | auto refDvp = dynamic_cast<TechDraw::DrawViewPart*>(refObj); |
| | if (refDvp) { |
| | ReferenceEntry fixedRef = searchViewForExactEdge(refDvp, refGeom); |
| | if (fixedRef.getObject()) { |
| | refToFix = fixedRef; |
| | return true; |
| | } |
| | } |
| |
|
| | |
| | return false; |
| | } |
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findExactVertex3d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | getMatcher()->setPointTolerance(EWTOLERANCE); |
| |
|
| | |
| | auto refObj = refToFix.getObject(); |
| | if (refObj) { |
| | ReferenceEntry fixedRef = searchObjForVert(refObj, refGeom); |
| | if (fixedRef.getObject()) { |
| | refToFix = fixedRef; |
| | return true; |
| | } |
| | } |
| |
|
| | |
| | for (auto& objectName : m_3dObjectCache) { |
| | auto object3d = getDimension()->getDocument()->getObject(objectName.c_str()); |
| | ReferenceEntry fixedRef = searchObjForVert(object3d, refGeom); |
| | if (fixedRef.getObject()) { |
| | refToFix = fixedRef; |
| | return true; |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, const Part::TopoShape& refGeom) const |
| | { |
| | |
| | |
| | auto refObj = refToFix.getObject(); |
| | if (refObj) { |
| | ReferenceEntry fixedRef = searchObjForEdge(refObj, refGeom); |
| | if (fixedRef.getObject()) { |
| | refToFix = fixedRef; |
| | return true; |
| | } |
| | } |
| |
|
| | |
| | for (auto& objectName : m_3dObjectCache) { |
| | auto object3d = getDimension()->getDocument()->getObject(objectName.c_str()); |
| | auto shape3d = Part::Feature::getShape(object3d, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); |
| | auto edgesAll = getDimension()->getEdges(shape3d); |
| | size_t iEdge {1}; |
| | for (auto& edge : edgesAll) { |
| | if (getMatcher()->compareGeometry(edge, refGeom)) { |
| | |
| | refToFix.setObjectName(objectName); |
| | refToFix.setObject(object3d); |
| | refToFix.setSubName(std::string("Edge") + std::to_string(iEdge)); |
| | return true; |
| | } |
| | iEdge++; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findSimilarVertex2d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | (void)refToFix; |
| | (void)refGeom; |
| | |
| | return false; |
| | } |
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::findSimilarEdge2d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | (void)refToFix; |
| | (void)refGeom; |
| | |
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | bool DimensionAutoCorrect::findSimilarVertex3d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | (void)refToFix; |
| | (void)refGeom; |
| | |
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | bool DimensionAutoCorrect::findSimilarEdge3d(ReferenceEntry& refToFix, |
| | const Part::TopoShape& refGeom) const |
| | { |
| | |
| | (void)refToFix; |
| | (void)refGeom; |
| | |
| | return false; |
| | } |
| |
|
| | |
| | bool DimensionAutoCorrect::isMatchingGeometry(const ReferenceEntry& ref, |
| | const Part::TopoShape& savedGeometry) const |
| | { |
| | Part::TopoShape temp; |
| | if (ref.is3d()) { |
| | auto shape3d = ShapeFinder::getLocatedShape(*ref.getObject(), ref.getSubName(true)); |
| | temp = Part::TopoShape(shape3d); |
| | } else { |
| | auto shape2d = ref.getGeometry(); |
| | temp = Part::TopoShape(shape2d); |
| | } |
| |
|
| |
|
| | if (temp.isNull()) { |
| | |
| | return false; |
| | } |
| | if (getMatcher()->compareGeometry(temp, savedGeometry)) { |
| | |
| | return true; |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | |
| | |
| | |
| | ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj, |
| | const Part::TopoShape& refVertex, |
| | bool exact) const |
| | { |
| | (void)exact; |
| | auto shape3d = ShapeFinder::getLocatedShape(*obj, ""); |
| | if (shape3d.IsNull()) { |
| | |
| | return {}; |
| | } |
| | auto vertsAll = getDimension()->getVertexes(shape3d); |
| | size_t iVert {1}; |
| | for (auto& vert : vertsAll) { |
| | bool isSame = getMatcher()->compareGeometry(refVertex, vert); |
| | if (isSame) { |
| | auto newSubname = std::string("Vertex") + std::to_string(iVert); |
| | return {obj, newSubname, getDimension()->getDocument()}; |
| | } |
| | iVert++; |
| | } |
| | return {}; |
| | } |
| |
|
| |
|
| | |
| | |
| | ReferenceEntry DimensionAutoCorrect::searchViewForVert(DrawViewPart* obj, |
| | const Part::TopoShape& refVertex, |
| | bool exact) const |
| | { |
| | |
| | (void)exact; |
| | std::vector<TechDraw::VertexPtr> gVertexAll = |
| | getDimension()->getViewPart()->getVertexGeometry(); |
| | getMatcher()->setPointTolerance(EWTOLERANCE); |
| | int iVertex = 0; |
| | for (auto& vert : gVertexAll) { |
| | |
| | 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()}; |
| | } |
| | iVertex++; |
| | } |
| | return {}; |
| | } |
| |
|
| | |
| | ReferenceEntry DimensionAutoCorrect::searchViewForExactEdge(DrawViewPart* obj, |
| | const Part::TopoShape& refEdge) const |
| | { |
| | |
| | auto gEdgeAll = getDimension()->getViewPart()->getEdgeGeometry(); |
| | int iEdge {0}; |
| | for (auto& edge : gEdgeAll) { |
| | |
| | |
| | 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); |
| | return {obj, newSubname, getDimension()->getDocument()}; |
| | } |
| | iEdge++; |
| | } |
| | return {}; |
| | } |
| |
|
| |
|
| | |
| | ReferenceEntry DimensionAutoCorrect::searchViewForSimilarEdge(DrawViewPart* obj, |
| | const Part::TopoShape& refEdge) const |
| | { |
| | |
| | (void)obj; |
| | (void)refEdge; |
| | Base::Console().message("DAC::searchViewForSimilarEdge is not implemented yet\n"); |
| | return {}; |
| | } |
| |
|
| | |
| | |
| | ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj, |
| | const Part::TopoShape& refEdge, |
| | bool exact) const |
| | { |
| | |
| | (void)exact; |
| | auto shape3d = Part::Feature::getShape(obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform); |
| | if (shape3d.IsNull()) { |
| | |
| | return {}; |
| | } |
| | auto edgesAll = getDimension()->getEdges(shape3d); |
| | size_t iEdge {1}; |
| | for (auto& edge : edgesAll) { |
| | bool isSame = getMatcher()->compareGeometry(edge, refEdge); |
| | if (isSame) { |
| | auto newSubname = std::string("Edge") + std::to_string(iEdge); |
| | return {obj, newSubname, getDimension()->getDocument()}; |
| | } |
| | iEdge++; |
| | } |
| | return {}; |
| | } |
| |
|
| | |
| | |
| | bool DimensionAutoCorrect::fixBrokenReferences(ReferenceVector& fixedReferences) const |
| | { |
| | |
| | bool success {true}; |
| | const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues(); |
| | int iGeom {0}; |
| | for (auto& geom : savedGeometry) { |
| | if (fixedReferences.at(iGeom).hasGeometry()) { |
| | iGeom++; |
| | continue; |
| | } |
| | |
| | const TopoDS_Shape& geomShape = geom.getShape(); |
| | for (auto& objectName : m_3dObjectCache) { |
| | auto object3d = getDimension()->getDocument()->getObject(objectName.c_str()); |
| | if (!object3d) { |
| | |
| | continue; |
| | } |
| | |
| | ReferenceEntry newRef; |
| | if (geomShape.ShapeType() == TopAbs_VERTEX) { |
| | newRef = searchObjForVert(object3d, geomShape); |
| | fixedReferences.at(iGeom) = newRef; |
| | } |
| | else { |
| | newRef = searchObjForEdge(object3d, geomShape); |
| | fixedReferences.at(iGeom) = newRef; |
| | } |
| | fixedReferences.at(iGeom) = newRef; |
| | if (!newRef.getObject()) { |
| | success = false; |
| | } |
| | } |
| | } |
| | return success; |
| | } |
| |
|
| |
|
| | GeometryMatcher* DimensionAutoCorrect::getMatcher() const |
| | { |
| | return getDimension()->getMatcher(); |
| | } |
| |
|
| |
|