From a52f4db613b20b4ff0997b4a1c1001d430daa287 Mon Sep 17 00:00:00 2001 From: dbv Date: Thu, 27 Sep 2018 14:43:40 +0300 Subject: [PATCH] Issue #2631: SIGSEGV when creating a point on the result of a cut edge by edge Don't store shape as deleted if it is present in any of the feature results. --- src/FeaturesPlugin/CMakeLists.txt | 1 + .../FeaturesPlugin_BooleanCut.cpp | 136 +++++++++++++----- .../FeaturesPlugin_BooleanCut.h | 13 ++ src/FeaturesPlugin/Test/Test2631.py | 62 ++++++++ src/Model/Model_BodyBuilder.cpp | 21 +-- src/Model/Model_BodyBuilder.h | 3 +- src/ModelAPI/ModelAPI_BodyBuilder.h | 3 +- src/ModelAPI/ModelAPI_ResultBody.cpp | 5 +- src/ModelAPI/ModelAPI_ResultBody.h | 3 +- 9 files changed, 199 insertions(+), 48 deletions(-) create mode 100644 src/FeaturesPlugin/Test/Test2631.py diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index d5decdfc8..07a31f551 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -366,4 +366,5 @@ ADD_UNIT_TESTS(TestExtrusion.py TestBooleanFuse_CompSolid_CompSolid.py TestBooleanFuse_CompSolidCompound_CompSolidCompound.py Test1816.py + Test2631.py ) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp index c4c4914e5..79b959e9b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.cpp @@ -32,6 +32,15 @@ #include #include +//================================================================================================== +const int ModifyVTag = 1; +const int ModifyETag = 2; +const int ModifyFTag = 3; +const int DeletedTag = 4; +/// sub solids will be placed at labels 5, 6, etc. if result is compound of solids +const int SubsolidsTag = 5; + + //================================================================================================== FeaturesPlugin_BooleanCut::FeaturesPlugin_BooleanCut() : FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_CUT) @@ -99,12 +108,15 @@ void FeaturesPlugin_BooleanCut::execute() return; } + std::vector aResultBaseAlgoList; + ListOfShape aResultShapesList; + // For solids cut each object with all tools. for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); ++anObjectsIt) { std::shared_ptr anObject = *anObjectsIt; - GeomAlgoAPI_MakeShapeList aMakeShapeList; + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); std::shared_ptr aCutAlgo( new GeomAlgoAPI_Boolean(anObject, aTools, @@ -128,7 +140,7 @@ void FeaturesPlugin_BooleanCut::execute() return; } - aMakeShapeList.appendAlgo(aCutAlgo); + aMakeShapeList->appendAlgo(aCutAlgo); GeomAPI_ShapeIterator aShapeIt(aResShape); if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX) @@ -137,10 +149,17 @@ void FeaturesPlugin_BooleanCut::execute() document()->createBody(data(), aResultIndex); loadNamingDS(aResultBody, anObject, aTools, aResShape, - aMakeShapeList, *(aCutAlgo->mapOfSubShapes()), + *aMakeShapeList, *(aCutAlgo->mapOfSubShapes()), false); setResult(aResultBody, aResultIndex); aResultIndex++; + + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = anObject; + aRBA.makeShape = aMakeShapeList; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back(aResShape); } } @@ -171,7 +190,7 @@ void FeaturesPlugin_BooleanCut::execute() } } - GeomAlgoAPI_MakeShapeList aMakeShapeList; + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); std::shared_ptr aCutAlgo( new GeomAlgoAPI_Boolean(aUsedInOperationSolids, aTools, @@ -194,7 +213,7 @@ void FeaturesPlugin_BooleanCut::execute() return; } - aMakeShapeList.appendAlgo(aCutAlgo); + aMakeShapeList->appendAlgo(aCutAlgo); GeomAPI_DataMapOfShapeShape aMapOfShapes; aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); GeomShapePtr aResultShape = aCutAlgo->shape(); @@ -211,7 +230,7 @@ void FeaturesPlugin_BooleanCut::execute() return; } - aMakeShapeList.appendAlgo(aFillerAlgo); + aMakeShapeList->appendAlgo(aFillerAlgo); aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); aResultShape = aFillerAlgo->shape(); } @@ -226,11 +245,18 @@ void FeaturesPlugin_BooleanCut::execute() aCompSolid, aTools, aResultShape, - aMakeShapeList, + *aMakeShapeList, aMapOfShapes, false); setResult(aResultBody, aResultIndex); aResultIndex++; + + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = aCompSolid; + aRBA.makeShape = aMakeShapeList; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back(aResultShape); } } @@ -261,7 +287,7 @@ void FeaturesPlugin_BooleanCut::execute() } } - GeomAlgoAPI_MakeShapeList aMakeShapeList; + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); std::shared_ptr aCutAlgo( new GeomAlgoAPI_Boolean(aUsedInOperationShapes, aTools, @@ -284,7 +310,7 @@ void FeaturesPlugin_BooleanCut::execute() return; } - aMakeShapeList.appendAlgo(aCutAlgo); + aMakeShapeList->appendAlgo(aCutAlgo); GeomAPI_DataMapOfShapeShape aMapOfShapes; aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); GeomShapePtr aResultShape = aCutAlgo->shape(); @@ -316,14 +342,26 @@ void FeaturesPlugin_BooleanCut::execute() aCompound, aTools, aResultShape, - aMakeShapeList, + *aMakeShapeList, aMapOfShapes, false); setResult(aResultBody, aResultIndex); aResultIndex++; + + ResultBaseAlgo aRBA; + aRBA.resultBody = aResultBody; + aRBA.baseShape = aCompound; + aRBA.makeShape = aMakeShapeList; + aResultBaseAlgoList.push_back(aRBA); + aResultShapesList.push_back(aResultShape); } } + // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one + // result shape has been deleted, but in another it was modified or stayed. + GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList); + storeDeletedShapes(aResultBaseAlgoList, aTools, aResultShapesCompound); + // remove the rest results if there were produced in the previous pass removeResults(aResultIndex); } @@ -341,53 +379,83 @@ void FeaturesPlugin_BooleanCut::loadNamingDS(ResultBodyPtr theResultBody, if(theBaseShape->isEqual(theResultShape)) { theResultBody->store(theResultShape, false); } else { - const int aModifyVTag = 1; - const int aModifyETag = 2; - const int aModifyFTag = 3; - const int aDeletedTag = 4; - /// sub solids will be placed at labels 5, 6, etc. if result is compound of solids - const int aSubsolidsTag = 5; - - theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); + theResultBody->storeModified(theBaseShape, theResultShape, SubsolidsTag); const std::string aModVName = "Modified_Vertex"; const std::string aModEName = "Modified_Edge"; const std::string aModFName = "Modified_Face"; theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX, - aModifyVTag, aModVName, theMapOfShapes, false, + ModifyVTag, aModVName, theMapOfShapes, false, theIsStoreAsGenerated, true); theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::EDGE, - aModifyETag, aModEName, theMapOfShapes, false, + ModifyETag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true); theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, - aModifyFTag, aModFName, theMapOfShapes, false, + ModifyFTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, - GeomAPI_Shape::VERTEX, aDeletedTag); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, - GeomAPI_Shape::EDGE, aDeletedTag); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, - GeomAPI_Shape::FACE, aDeletedTag); - for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, - aModifyVTag, aModVName, theMapOfShapes, false, + ModifyVTag, aModVName, theMapOfShapes, false, theIsStoreAsGenerated, true); theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, - aModifyETag, aModEName, theMapOfShapes, false, + ModifyETag, aModEName, theMapOfShapes, false, theIsStoreAsGenerated, true); theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, - aModifyFTag, aModFName, theMapOfShapes, false, + ModifyFTag, aModFName, theMapOfShapes, false, theIsStoreAsGenerated, true); + } + } +} + +//================================================================================================== +void FeaturesPlugin_BooleanCut::storeDeletedShapes( + std::vector& theResultBaseAlgoList, + const ListOfShape& theTools, + const GeomShapePtr theResultShapesCompound) +{ + for (std::vector::iterator anIt = theResultBaseAlgoList.begin(); + anIt != theResultBaseAlgoList.end(); + ++anIt) + { + ResultBaseAlgo& aRCA = *anIt; + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + aRCA.baseShape, + GeomAPI_Shape::VERTEX, + DeletedTag, + theResultShapesCompound); + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + aRCA.baseShape, + GeomAPI_Shape::EDGE, + DeletedTag, + theResultShapesCompound); + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + aRCA.baseShape, + GeomAPI_Shape::FACE, + DeletedTag, + theResultShapesCompound); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::VERTEX, aDeletedTag); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::EDGE, aDeletedTag); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag); + for (ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) + { + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + *anIter, + GeomAPI_Shape::VERTEX, + DeletedTag, + theResultShapesCompound); + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + *anIter, + GeomAPI_Shape::EDGE, + DeletedTag, + theResultShapesCompound); + aRCA.resultBody->loadDeletedShapes(aRCA.makeShape.get(), + *anIter, + GeomAPI_Shape::FACE, + DeletedTag, + theResultShapesCompound); } } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.h b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.h index 4ae4463eb..11c154ced 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.h +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanCut.h @@ -55,6 +55,14 @@ public: /// Use plugin manager for features creation. FeaturesPlugin_BooleanCut(); +private: + + struct ResultBaseAlgo { + ResultBodyPtr resultBody; + GeomShapePtr baseShape; + std::shared_ptr makeShape; + }; + private: /// Load Naming data structure of the feature to the document @@ -66,6 +74,11 @@ private: GeomAPI_DataMapOfShapeShape& theMapOfShapes, const bool theIsStoreAsGenerated = false); + /// Stores deleted shapes. + void storeDeletedShapes(std::vector& theResultBaseAlgoList, + const ListOfShape& theTools, + const GeomShapePtr theResultShapesCompound); + }; #endif diff --git a/src/FeaturesPlugin/Test/Test2631.py b/src/FeaturesPlugin/Test/Test2631.py new file mode 100644 index 000000000..a254a0723 --- /dev/null +++ b/src/FeaturesPlugin/Test/Test2631.py @@ -0,0 +1,62 @@ +## 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 SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-53.93497380447579, 58.11303515552675, 60.01215395145899, 58.11303515552675) +SketchLine_2 = Sketch_1.addLine(60.01215395145899, 58.11303515552675, 60.01215395145899, 11.01488901640705) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_3 = Sketch_2.addLine(31.90519577166173, 58.11303515552675, 60.012153951459, 58.11303515552675) +SketchProjection_1 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), False) +SketchLine_4 = SketchProjection_1.createdFeature() +SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_3.startPoint(), SketchLine_4.result()) +SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_4).endPoint(), SketchLine_3.endPoint()) +SketchLine_5 = Sketch_2.addLine(60.012153951459, 58.11303515552675, 60.012153951459, 33.0446670492211) +SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_3.endPoint(), SketchLine_5.startPoint()) +SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "Sketch_1/Edge-SketchLine_2"), False) +SketchLine_6 = SketchProjection_2.createdFeature() +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.result()) +model.do() +Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/Edge-SketchLine_1"), model.selection("EDGE", "Sketch_1/Edge-SketchLine_2")]) +Edge_2 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/Edge-SketchLine_3"), model.selection("EDGE", "Sketch_2/Edge-SketchLine_5")]) +Cut_1 = model.addCut(Part_1_doc, [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2")], [model.selection("EDGE", "Edge_2_1"), model.selection("EDGE", "Edge_2_2")]) +model.testHaveNamingSubshapes(Cut_1, model, Part_1_doc) +model.do() +model.end() + +from GeomAPI import GeomAPI_Shape + +model.testNbResults(Cut_1, 2) +model.testNbSubResults(Cut_1, [0, 0]) +model.testNbSubShapes(Cut_1, GeomAPI_Shape.SOLID, [0, 0]) +model.testNbSubShapes(Cut_1, GeomAPI_Shape.FACE, [0, 0]) +model.testNbSubShapes(Cut_1, GeomAPI_Shape.EDGE, [1, 1]) +model.testNbSubShapes(Cut_1, GeomAPI_Shape.VERTEX, [2, 2]) + +assert(model.checkPythonDump()) diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 82f33b986..365afd726 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -364,7 +364,8 @@ void Model_BodyBuilder::deleted(const std::shared_ptr& theOldShap void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, const int theKindOfShape, - const int theTag) + const int theTag, + const GeomShapePtr theShapes) { TopoDS_Shape aShapeIn = theShapeIn->impl(); TopTools_MapOfShape aView; @@ -375,15 +376,17 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, if (!aView.Add(aRoot)) continue; std::shared_ptr aRShape(new GeomAPI_Shape()); aRShape->setImpl((new TopoDS_Shape(aRoot))); - if (theMS->isDeleted (aRShape)) { - if (!aResultShape->isSubShape(aRShape, false)) { - ListOfShape aHist; - if (BRepTools_History::IsSupportedType(aRoot)) // to avoid crash in #2572 - theMS->modified(aRShape, aHist); - if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape))) - builder(theTag)->Delete(aRoot); - } + if (!theMS->isDeleted(aRShape) + || aResultShape->isSubShape(aRShape, false) + || (theShapes.get() && theShapes->isSubShape(aRShape, false))) { + continue; } + + ListOfShape aHist; + if (BRepTools_History::IsSupportedType(aRoot)) // to avoid crash in #2572 + theMS->modified(aRShape, aHist); + if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape))) + builder(theTag)->Delete(aRoot); } } diff --git a/src/Model/Model_BodyBuilder.h b/src/Model/Model_BodyBuilder.h index 2c8f56321..d34fb0b17 100755 --- a/src/Model/Model_BodyBuilder.h +++ b/src/Model/Model_BodyBuilder.h @@ -92,7 +92,8 @@ public: MODEL_EXPORT virtual void loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, const int theKindOfShape, - const int theTag); + const int theTag, + const GeomShapePtr theShapes = GeomShapePtr()); /// load and orient modified shapes MODEL_EXPORT virtual void loadAndOrientModifiedShapes ( GeomAlgoAPI_MakeShape* theMS, diff --git a/src/ModelAPI/ModelAPI_BodyBuilder.h b/src/ModelAPI/ModelAPI_BodyBuilder.h index 8524cc31d..8da3d2158 100755 --- a/src/ModelAPI/ModelAPI_BodyBuilder.h +++ b/src/ModelAPI/ModelAPI_BodyBuilder.h @@ -88,7 +88,8 @@ public: virtual void loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, const int theKindOfShape, - const int theTag) = 0; + const int theTag, + const GeomShapePtr theShapes = GeomShapePtr()) = 0; /// load and orient modified shapes virtual void loadAndOrientModifiedShapes ( GeomAlgoAPI_MakeShape* theMS, diff --git a/src/ModelAPI/ModelAPI_ResultBody.cpp b/src/ModelAPI/ModelAPI_ResultBody.cpp index ba28f8b90..0ee6696c2 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.cpp +++ b/src/ModelAPI/ModelAPI_ResultBody.cpp @@ -128,9 +128,10 @@ void ModelAPI_ResultBody::deleted( void ModelAPI_ResultBody::loadDeletedShapes(GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, const int theKindOfShape, - const int theTag) + const int theTag, + const GeomShapePtr theShapes) { - myBuilder->loadDeletedShapes(theMS, theShapeIn, theKindOfShape, theTag); + myBuilder->loadDeletedShapes(theMS, theShapeIn, theKindOfShape, theTag, theShapes); } void ModelAPI_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS, diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index cb17e6522..b934744c6 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -140,7 +140,8 @@ public: MODELAPI_EXPORT virtual void loadDeletedShapes(GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, const int theKindOfShape, - const int theTag); + const int theTag, + const GeomShapePtr theShapes = GeomShapePtr()); /// load and orient modified shapes MODELAPI_EXPORT virtual void loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS, -- 2.39.2