From ecd0a4691b938201f97329f61ecd001a361c2909 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 16 Jan 2018 16:08:59 +0300 Subject: [PATCH] Fix for #2389 - sketch points selected that are located not on sketch compound of edges intersection --- src/Model/Model_ResultConstruction.cpp | 55 ++++++++++++---- src/Model/Model_SelectionNaming.cpp | 90 +++++++++++++++++--------- src/Model/Model_SelectionNaming.h | 4 ++ src/ModelAPI/CMakeLists.txt | 1 + src/ModelAPI/Test/Test2389.py | 69 ++++++++++++++++++++ 5 files changed, 178 insertions(+), 41 deletions(-) create mode 100644 src/ModelAPI/Test/Test2389.py diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index 127507249..a5230dd33 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -363,17 +363,50 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu // if the subshape is part of a result face, select the whole face (#1997) bool isSelectionMode = false; // and other don't set shapes - all the naming is in face label if (!aSubShape.IsNull() && aSubShape.ShapeType() > TopAbs_FACE) { - for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) { - TopExp_Explorer anExp(face(aFaceIndex)->impl(), aSubShape.ShapeType()); - for(; anExp.More(); anExp.Next()) { - if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face - // here just store the face index (to update face if update of edge is needed) - TNaming_Builder aBuilder(aLab); - aBuilder.Select(aSubShape, aSubShape); - int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1); - TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID)); - isSelectionMode = true; - break; + // but before check that sub-vertex correctly detected as intersection of sketch edges (#2389) + int anEdgesNum = 2; + if (aSubShape.ShapeType() == TopAbs_VERTEX) { + anEdgesNum = 0; + ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); + FeaturePtr aThisFeature = document()->feature(aThisPtr); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aThisFeature); + if (aComposite.get()) { + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + int aSubID = aComposite->subFeatureId(a); + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes; + for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + TopoDS_Shape aResShape = aConstr->shape()->impl(); + for(TopExp_Explorer anExp(aResShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) { + if (aSubShape.IsSame(anExp.Current())) { + anEdgesNum++; + break; + } + } + } + } + } + } + } + if (anEdgesNum > 1) { + for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) { + TopExp_Explorer anExp(face(aFaceIndex)->impl(), aSubShape.ShapeType()); + for(; anExp.More(); anExp.Next()) { + if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face + // here just store the face index (to update face if update of edge is needed) + TNaming_Builder aBuilder(aLab); + aBuilder.Select(aSubShape, aSubShape); + int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1); + TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID)); + isSelectionMode = true; + break; + } } } } diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 8c794c3dc..fd7b72f13 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -256,6 +256,38 @@ const TopoDS_Shape findCommonShape( return aSharedShape; } +std::string Model_SelectionNaming::vertexNameByEdges(TopoDS_Shape theContext, TopoDS_Shape theSub, + std::shared_ptr theDoc, ResultPtr& theContextRes, const bool theAnotherDoc) +{ + std::string aResult; + TopTools_IndexedDataMapOfShapeListOfShape aMap; + TopExp::MapShapesAndAncestors(theContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); + const TopTools_ListOfShape& aList22 = aMap.FindFromKey(theSub); + if(aList22.Extent() >= 2) { // regular solution + TopTools_MapOfShape aFMap; + TopTools_ListOfShape aListE; + TopTools_ListIteratorOfListOfShape itl2(aList22); + for (int i = 1;itl2.More();itl2.Next(),i++) { + if(aFMap.Add(itl2.Value())) + aListE.Append(itl2.Value()); + } + TopTools_ListIteratorOfListOfShape itl(aListE); + for (int i = 1;itl.More();itl.Next(),i++) { + const TopoDS_Shape& anEdge = itl.Value(); + std::string anEdgeName = getShapeName(theDoc, anEdge, theContextRes, theAnotherDoc, false); + if (anEdgeName.empty()) { // edge is not in DS + aResult.clear(); + return aResult; + } + if(i == 1) + aResult = anEdgeName; + else + aResult += "&" + anEdgeName; + } + } + return aResult; +} + std::string Model_SelectionNaming::namingName(ResultPtr& theContext, std::shared_ptr theSubSh, const std::string& theDefaultName, const bool theAnotherDoc) @@ -396,40 +428,24 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopoDS_Shape aVertex = findCommonShape(TopAbs_VERTEX, aList); isByFaces = !aVertex.IsNull() && aVertex.ShapeType() == TopAbs_VERTEX; } - if(!isByFaces) { // open topology case or Compound case => via edges - TopTools_IndexedDataMapOfShapeListOfShape aMap; - TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap); - const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape); - if(aList22.Extent() >= 2) { // regular solution - // bug! duplication; fix is below - aFMap.Clear(); - TopTools_ListOfShape aListE; - TopTools_ListIteratorOfListOfShape itl2(aList22); - for (int i = 1;itl2.More();itl2.Next(),i++) { - if(aFMap.Add(itl2.Value())) - aListE.Append(itl2.Value()); - } - n = aListE.Extent(); - TopTools_ListIteratorOfListOfShape itl(aListE); - for (int i = 1;itl.More();itl.Next(),i++) { - const TopoDS_Shape& anEdge = itl.Value(); - std::string anEdgeName = getShapeName(aDoc, anEdge, theContext, theAnotherDoc, false); - if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway - isByFaces = true; - aName.clear(); - break; + if(!isByFaces) { // open topology case or Compound case => via edges + aName = vertexNameByEdges(aContext, aSubShape, aDoc, theContext, theAnotherDoc); + isByFaces = aName.empty(); + if (isByFaces) { // try to find a vertex in sketch faces + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(theContext); + if (aConstr.get() && aConstr->facesNum()) { + for(int aFace = aConstr->facesNum() - 1; isByFaces && aFace >= 0; aFace--) { + std::shared_ptr aGFace = aConstr->face(aFace); + aName = vertexNameByEdges(aGFace->impl(), aSubShape, + aDoc, theContext, theAnotherDoc); + isByFaces = aName.empty(); } - if(i == 1) - aName = anEdgeName; - else - aName += "&" + anEdgeName; } - }//reg - else { // dangle vertex: if(aList22.Extent() == 1) - //it should be already in DF } } + if (isByFaces) { TopTools_ListIteratorOfListOfShape itl(aList); for (int i = 1;itl.More();itl.Next(),i++) { @@ -445,7 +461,6 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, break; } } - return aName; } @@ -1058,6 +1073,21 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, } } } + } else if (aSelection.IsNull() && aN >= 2 && aType == TopAbs_VERTEX) { + // support of shape name as intersection separated by "&" + static std::string anEdgeType = "edge"; // for now it works only with su-edges + std::list::iterator aSubNames = aListofNames.begin(); + TopTools_ListOfShape aSubsList; + for(; aSubNames != aListofNames.end(); aSubNames++) { + std::string aSubName = *aSubNames; + std::shared_ptr aSubShapeFound; + std::shared_ptr aContextFound; + if (selectSubShape(anEdgeType, aSubName, theDoc, aSubShapeFound, aContextFound)) { + if (aSubShapeFound.get()) + aSubsList.Append(aSubShapeFound->impl()); + } + } + aSelection = findCommonShape(TopAbs_VERTEX, aSubsList); } if (!aSelection.IsNull()) { // Select it (must be after N=0 checking, diff --git a/src/Model/Model_SelectionNaming.h b/src/Model/Model_SelectionNaming.h index ff49de7bc..d6ebc7137 100644 --- a/src/Model/Model_SelectionNaming.h +++ b/src/Model/Model_SelectionNaming.h @@ -83,6 +83,10 @@ protected: /// Gets the stored name from the document std::string getShapeName(std::shared_ptr theDoc, const TopoDS_Shape& theShape, ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext); + + /// Tries to find the name of the context sub-shape as combination of edges in context + std::string vertexNameByEdges(TopoDS_Shape theContext, TopoDS_Shape theSub, + std::shared_ptr theDoc, ResultPtr& theContextRes, const bool theAnotherDoc); }; #endif diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 06d800a57..918c55999 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -174,6 +174,7 @@ ADD_UNIT_TESTS(TestConstants.py Test2241.py Test2252.py Test2276.py + Test2389.py Test2391.py TestCustomName_BooleanCut.py TestCustomName_CommonCompSolid.py diff --git a/src/ModelAPI/Test/Test2389.py b/src/ModelAPI/Test/Test2389.py new file mode 100644 index 000000000..89121b8a7 --- /dev/null +++ b/src/ModelAPI/Test/Test2389.py @@ -0,0 +1,69 @@ +## Copyright (C) 2014-2017 CEA/DEN, EDF R&D +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## See http:##www.salome-platform.org/ or +## email : webmaster.salome@opencascade.com +## + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +model.addParameter(Part_1_doc, "Width", "64") +model.addParameter(Part_1_doc, "Drill2_Loc", "6.5") +model.addParameter(Part_1_doc, "Drill2_Radius", "1.4") +model.addParameter(Part_1_doc, "Drill2_InnerRadius", "0.5") +model.addParameter(Part_1_doc, "Drill2_DepthMin", "6.5") +model.addParameter(Part_1_doc, "Drill2_DepthMax", "7.5") +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(64., 0, 0, 0) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result()) +SketchLine_2 = Sketch_1.addLine(0, 0, 0, 36) +SketchLine_3 = Sketch_1.addLine(0, 36, 64, 36) +SketchLine_4 = Sketch_1.addLine(64, 36, 64, 0) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.startPoint(), SketchLine_3.endPoint(), "Width") +SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 36) +SketchLine_5 = Sketch_1.addLine(22, 36, 22, 0) +SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_3.result()) +SketchLine_6 = Sketch_1.addLine(32., 36., 32., 0) +SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_6.startPoint(), SketchLine_3.result()) +SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_1.result()) +SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.result()) +SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_5.result()) +SketchConstraintVertical_4 = Sketch_1.setVertical(SketchLine_6.result()) +SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_2.endPoint(), SketchLine_5.startPoint(), "Width/32*11") +SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchLine_6.startPoint(), SketchLine_3.endPoint(), "Width/2") +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_5s"), True) +SketchPoint_2 = SketchProjection_2.createdFeature() +model.end() + +assert(SketchProjection_2.external().namingName() != "") + +assert(model.checkPythonDump()) -- 2.39.2