From: mpv Date: Fri, 18 Jan 2019 15:00:22 +0000 (+0300) Subject: Initial implementation of higher level objects history for partition X-Git-Tag: HighLevelObjectsHierarchy~13^2~32 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=c125ff07b907f94c4e768e9b5258703ae28da526;p=modules%2Fshaper.git Initial implementation of higher level objects history for partition --- diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index d0f0261a0..0458345a1 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -433,6 +433,7 @@ ADD_UNIT_TESTS(TestExtrusion.py TestScale1.py TestScale2.py Test1816.py + Test1876.py Test2631.py Test2650.py Test2681.py diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index 43ae4130c..8215f0293 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -172,37 +172,20 @@ void FeaturesPlugin_Partition::storeResult( const std::shared_ptr theMakeShape, const int theIndex) { - // Find base. The most complicated is the real modified object (#1799 if box is partitioned by - // two planes the box is the base, not planes, independently on the order in the list). - GeomShapePtr aBaseShape; - for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { - GeomShapePtr anObjectShape = *anIt; - GeomShapePtr aCandidate = - findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape); - if(!aCandidate.get()) { - aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape); - } - if (!aCandidate.get()) - aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape); - - if(aCandidate.get()) { - if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) { - aBaseShape = aCandidate; - } - } - } - // Create result body. ResultBodyPtr aResultBody = document()->createBody(data(), theIndex); - // Store modified shape. - if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) { - aResultBody->store(theResultShape, false); - setResult(aResultBody, theIndex); - return; + // if result is same as one of the base object, no modification was performed + for(ListOfShape::const_iterator anObj = theObjects.cbegin(); anObj != theObjects.cend(); ++anObj) + { + if (anObj->get() && (*anObj)->isSame(theResultShape)) { + aResultBody->store(theResultShape, false); + setResult(aResultBody, theIndex); + return; + } } - aResultBody->storeModified(aBaseShape, theResultShape); + aResultBody->storeModified(theObjects, theResultShape, theMakeShape); std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end()); @@ -222,38 +205,6 @@ void FeaturesPlugin_Partition::storeResult( //================= Auxiliary functions =================================================== -GeomShapePtr findBase(const GeomShapePtr theObjectShape, - const GeomShapePtr theResultShape, - const GeomAPI_Shape::ShapeType theShapeType, - const std::shared_ptr theMakeShape) -{ - GeomShapePtr aBaseShape; - std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); - for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType); - anObjectSubShapesExp.more(); - anObjectSubShapesExp.next()) { - GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current(); - ListOfShape aModifiedShapes; - theMakeShape->modified(anObjectSubShape, aModifiedShapes); - for(ListOfShape::const_iterator - aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) { - GeomShapePtr aModShape = *aModIt; - if(aMapOfSubShapes->isBound(aModShape)) { - aModShape = aMapOfSubShapes->find(aModShape); - } - if(theResultShape->isSubShape(aModShape)) { - aBaseShape = theObjectShape; - break; - } - } - if(aBaseShape.get()) { - break; - } - } - - return aBaseShape; -} - static CompsolidSubs::iterator findOrAdd(CompsolidSubs& theList, const GeomShapePtr& theCompsolid) { CompsolidSubs::iterator aFound = theList.begin(); diff --git a/src/FeaturesPlugin/Test/Test1876.py b/src/FeaturesPlugin/Test/Test1876.py new file mode 100644 index 000000000..4b01039f9 --- /dev/null +++ b/src/FeaturesPlugin/Test/Test1876.py @@ -0,0 +1,72 @@ +## 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 +from ModelAPI import * + +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(396.8373493975904, 115.9638554216867, -225.1506024096385, 115.9638554216867) +SketchLine_2 = Sketch_1.addLine(-225.1506024096385, 115.9638554216867, -225.1506024096385, -149.0963855421687) +SketchLine_3 = Sketch_1.addLine(-225.1506024096385, -149.0963855421687, 396.8373493975904, -149.0963855421687) +SketchLine_4 = Sketch_1.addLine(396.8373493975904, -149.0963855421687, 396.8373493975904, 115.9638554216867) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = 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()) +model.do() +Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_2.addCircle(-348.644578313253, 155.1204819277109, 207.6894050099908) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 100, 0) +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2r")], model.selection(), 100, 0) +Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")]) +Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")]) +Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")]) +model.end() + +# move groups +model.begin() +Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature()) +Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature()) +model.end() + +# check each group contain two results: one is related to original body only, another - common part + +aFactory = ModelAPI_Session.get().validators() +assert(aFactory.validate(Group_1.feature())) +assert(aFactory.validate(Group_2.feature())) +aList1 = Group_1.feature().selectionList("group_list") +aList2 = Group_2.feature().selectionList("group_list") +assert(aList1.size() == 2) +assert(aList2.size() == 2) +assert(aList1.value(0).value().shapeTypeStr() == "SOLID") +assert(aList1.value(1).value().shapeTypeStr() == "SOLID") +assert(aList2.value(0).value().shapeTypeStr() == "SOLID") +assert(aList2.value(1).value().shapeTypeStr() == "SOLID") +assert(aList1.value(0).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(0).value()) or +aList1.value(1).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(1).value())) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 00736a73e..6940cdbe1 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1373,75 +1373,12 @@ void Model_AttributeSelection::updateInHistory() continue; } - ResultPtr aSetContext; if (aFirst) { setValue(*aNewCont, aValueShape); - aSetContext = context(); + aFirst = false; } else if (myParent) { myParent->append(*aNewCont, aValueShape); - aSetContext = myParent->value(myParent->size() - 1)->context(); } - - // #2826 : error if context is concealed by new context where the value is not presented - if (aSetContext.get()) { - bool anError = false; - std::list allRes; - ResultPtr aCompContext; - ResultBodyPtr aCompBody = ModelAPI_Tools::bodyOwner(aSetContext, true); - if (aCompBody.get()) { - ModelAPI_Tools::allSubs(aCompBody, allRes); - allRes.push_back(aCompBody); - aCompContext = aCompBody; - } - if (allRes.empty()) - allRes.push_back(aSetContext); - - std::list::iterator aSub = allRes.begin(); - for (; !anError && aSub != allRes.end(); aSub++) { - ResultPtr aResCont = *aSub; - ResultBodyPtr aResBody = std::dynamic_pointer_cast(aResCont); - const std::set& aRefs = aResCont->data()->refsToMe(); - std::set::const_iterator aRef = aRefs.begin(); - for (; aRef != aRefs.end(); aRef++) { - if (!aRef->get() || !(*aRef)->owner().get()) - continue; - // concealed attribute only - FeaturePtr aRefFeat = std::dynamic_pointer_cast((*aRef)->owner()); - if (!aRefFeat.get()) - continue; - if (!ModelAPI_Session::get()->validators()->isConcealed( - aRefFeat->getKind(), (*aRef)->id())) - continue; - // check the found feature is older than this attribute - if (aRefFeat == aThisFeature || aDoc->isLaterByDep(aRefFeat, aThisFeature)) - continue; - // check the found feature don't have the value-shape - GeomShapePtr aValue = aFirst ? value() : myParent->value(myParent->size() - 1)->value(); - if (aValue.get()) { - std::list::const_iterator aRefResults = aRefFeat->results().cbegin(); - for(; aRefResults != aRefFeat->results().cend(); aRefResults++) { - if ((*aRefResults)->shape().get() && - !(*aRefResults)->shape()->isSubShape(aValue, false)) { // set error - ResultPtr anEmptyContext; - std::shared_ptr anEmptyShape; - if (aFirst) { - setValue(anEmptyContext, anEmptyShape); // nullify the selection - } else { - myParent->value(myParent->size() - 1)->setValue(anEmptyContext, anEmptyShape); - } - Events_InfoMessage("Model_AttributeSelection", - "Selection of sub-shape of already modified result").send(); - anError = true; - break; - } - } - if (anError) - break; - } - } - } - } - aFirst = false; } if (aFirst) { // nothing was added, all results were deleted ResultPtr anEmptyContext; diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 7efd13fe8..893b4fc1c 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -166,13 +166,14 @@ void Model_BodyBuilder::store(const GeomShapePtr& theShape, } void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape, - const GeomShapePtr& theToShape) + const GeomShapePtr& theToShape, const bool theIsCleanStored) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { TDF_Label aShapeLab = aData->shapeLab(); // clean builders - clean(); + if (theIsCleanStored) + clean(); // store the new shape as primitive TNaming_Builder aBuilder(aShapeLab); if (!theFromShape || !theToShape) @@ -199,6 +200,31 @@ void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape, } } +void Model_BodyBuilder::storeGenerated(const std::list& theFromShapes, + const GeomShapePtr& theToShape, const std::shared_ptr theMakeShape) +{ + bool aStored = false; + std::list::const_iterator anOldIter = theFromShapes.cbegin(); + for(; anOldIter != theFromShapes.cend(); anOldIter++) { + ListOfShape aNews; // check this old really generates theToShape + theMakeShape->generated(*anOldIter, aNews); + ListOfShape::iterator aNewIter = aNews.begin(); + for(; aNewIter != aNews.end(); aNewIter++) { + if (theToShape->isSame(*aNewIter)) + break; + } + if (aNewIter != aNews.end()) { + storeGenerated(*anOldIter, theToShape, !aStored); + TNaming_Builder* aBuilder = builder(0); + aStored = !aBuilder->NamedShape()->IsEmpty(); + } + } + if (!aStored) { // store as PRIMITIVE, but clean in any way + store(theToShape); + return; + } +} + TNaming_Builder* Model_BodyBuilder::builder(const int theTag) { std::map::iterator aFind = myBuilders.find(theTag); @@ -232,7 +258,7 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape, aBuilder->Modify(aShapeOld, aShapeNew); if(!aBuilder->NamedShape()->IsEmpty()) { Handle(TDataStd_Name) anAttr; - if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { + if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) { std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); if(!aName.empty()) { std::shared_ptr aDoc = @@ -244,6 +270,31 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape, } } +void Model_BodyBuilder::storeModified(const std::list& theOldShapes, + const GeomShapePtr& theNewShape, const std::shared_ptr theMakeShape) +{ + bool aStored = false; + std::list::const_iterator anOldIter = theOldShapes.cbegin(); + for(; anOldIter != theOldShapes.cend(); anOldIter++) { + ListOfShape aNews; // check this old really modifies theNewShape + theMakeShape->modified(*anOldIter, aNews); + ListOfShape::iterator aNewIter = aNews.begin(); + for(; aNewIter != aNews.end(); aNewIter++) { + if (theNewShape->isSame(*aNewIter)) + break; + } + if (aNewIter != aNews.end()) { + storeModified(*anOldIter, theNewShape, !aStored); + TNaming_Builder* aBuilder = builder(0); + aStored = !aBuilder->NamedShape()->IsEmpty(); + } + } + if (!aStored) { // store as PRIMITIVE, but clean in any way + store(theNewShape); + return; + } +} + void Model_BodyBuilder::clean() { TDF_Label aLab = std::dynamic_pointer_cast(data())->shapeLab(); @@ -528,44 +579,18 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo, bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape); bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false); - if (aNewShapeIsSameAsOldShape - || aNewShapeIsNotInResultShape) - { + if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape) continue; - } - TNaming_Builder* aBuilder; - if (aResultShape->isSame(aNewShape)) { - // keep the modification evolution on the root level (2241 - history propagation issue) - aBuilder = builder(0); - TDF_Label aShapeLab = aBuilder->NamedShape()->Label(); - Handle(TDF_Reference) aRef; - if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) { - // Store only in case if it does not have reference. - continue; - } - - // Check if new shape was already stored. - if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue; - - if (!aBuilder->NamedShape().IsNull() && - ((isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_GENERATED) - || (!isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_MODIFY))) - { - myBuilders.erase(0); // clear old builder to avoid different evolutions crash - aBuilder = builder(0); - } - } else { - int aTag = isGenerated ? getGenerationTag(aNewShape_) - : getModificationTag(aNewShape_); - aBuilder = builder(aTag); + if (aResultShape->isSame(aNewShape)) + continue; // it is stored on the root level (2241 - history propagation issue) - // Check if new shape was already stored. - if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue; - - buildName(aTag, theName); - } + int aTag = isGenerated ? getGenerationTag(aNewShape_) : getModificationTag(aNewShape_); + TNaming_Builder*aBuilder = builder(aTag); + if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) + continue; // new shape was already stored. + buildName(aTag, theName); isGenerated ? aBuilder->Generated(anOldSubShape_, aNewShape_) : aBuilder->Modify(anOldSubShape_, aNewShape_); // store information about the external document reference to restore old shape on open @@ -632,25 +657,6 @@ void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo, storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label()); } buildName(aTag, theName); - } if (aResultShape->isSame(aNewShape)) { - // keep the generation evolution on the root level (2397 - for intersection feature) - TNaming_Builder* aBuilder = builder(0); - TDF_Label aShapeLab = aBuilder->NamedShape()->Label(); - Handle(TDF_Reference) aRef; - if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) { - // Store only in case if it does not have reference. - continue; - } - - // Check if new shape was already stored. - if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue; - - if (!aBuilder->NamedShape().IsNull() && - aBuilder->NamedShape()->Evolution() != TNaming_GENERATED) { - myBuilders.erase(0); // clear old builder to avoid different evolutions crash - aBuilder = builder(0); - } - aBuilder->Generated(anOldSubShape_, aNewShape_); } else { int aTag = getGenerationTag(aNewShape_); if (aTag == INVALID_TAG) return; diff --git a/src/Model/Model_BodyBuilder.h b/src/Model/Model_BodyBuilder.h index 8487a6b81..17e7635ea 100755 --- a/src/Model/Model_BodyBuilder.h +++ b/src/Model/Model_BodyBuilder.h @@ -42,21 +42,34 @@ class Model_BodyBuilder : public ModelAPI_BodyBuilder public: /// Stores the shape (called by the execution method). MODEL_EXPORT virtual void store(const GeomShapePtr& theShape, - const bool theIsStoreSameShapes = true); + const bool theIsStoreSameShapes = true) override; /// Stores the generated shape (called by the execution method). MODEL_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape, - const GeomShapePtr& theToShape); + const GeomShapePtr& theToShape, + const bool theIsCleanStored = true) override; + + /// Stores the root generated shapes (called by the execution method). + MODEL_EXPORT virtual void storeGenerated(const std::list& theFromShapes, + const GeomShapePtr& theToShape, + const std::shared_ptr theMakeShape) override; /// Stores the modified shape (called by the execution method). /// \param theOldShape shape that produces result /// \param theNewShape resulting shape - /// \param theDecomposeSolidsTag tag for starting of solids sub-elements placement in case - /// theNewShape is compound of solids, if zero it is not used + /// \param theIsCleanStored erases all previous data structure of this body if true MODEL_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape, const GeomShapePtr& theNewShape, const bool theIsCleanStored = true) override; + /// Stores the root modified shape (called by the execution method). + /// \param theOldShapes all shapes that produce result + /// \param theNewShape resulting shape + /// \param theIsCleanStored erases all previous data structure of this body if true + MODEL_EXPORT virtual void storeModified(const std::list& theOldShapes, + const GeomShapePtr& theNewShape, + const std::shared_ptr theMakeShape) override; + /// Returns the shape-result produced by this feature MODEL_EXPORT virtual GeomShapePtr shape(); diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 4acd17d8f..8368220f9 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -95,31 +95,12 @@ void Model_ResultBody::loadModifiedShapes(const std::shared_ptrisNewShapesCollected(theOldShape, theShapeTypeToExplore)) theAlgo->collectNewShapes(theOldShape, theShapeTypeToExplore); std::vector::const_iterator aSubIter = mySubs.cbegin(); for(; aSubIter != mySubs.cend(); aSubIter++) { - // check that sub-shape was also created as modification of ShapeIn - /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives - GeomShapePtr aSubGeomShape = (*aSubIter)->shape(); - if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) { - TopoDS_Shape aSubShape = aSubGeomShape->impl(); - TopoDS_Shape aWholeIn = theShapeIn->impl(); - for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) { - ListOfShape aHistory; - std::shared_ptr aSubIn(new GeomAPI_Shape()); - aSubIn->setImpl((new TopoDS_Shape(anExp.Current()))); - theMS->modified(aSubIn, aHistory); - std::list >::const_iterator anIt = aHistory.begin(); - for (; anIt != aHistory.end(); anIt++) { - if ((*anIt)->isSame(aSubGeomShape)) { - (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing - } - } - } - }*/ (*aSubIter)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName); } } else { // do for this directly @@ -273,7 +254,14 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS } GeomShapePtr anOldSubShape = aSub->shape(); if (!aShape->isEqual(anOldSubShape)) { - aSub->store(aShape, false); + if (myAlgo.get()) { + std::list anOldForSub; + computeOldForSub(aShape, anOldForSub); + myIsGenerated ? aSub->storeGenerated(anOldForSub, aShape, myAlgo) : + aSub->storeModified(anOldForSub, aShape, myAlgo); + } else { + aSub->store(aShape, false); + } aECreator->sendUpdated(aSub, EVENT_DISP); aECreator->sendUpdated(aSub, EVENT_UPD); } @@ -311,6 +299,19 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS } } +void Model_ResultBody::updateSubs( + const GeomShapePtr& theThisShape, const std::list& theOlds, + const std::shared_ptr theMakeShape, const bool isGenerated) +{ + myAlgo = theMakeShape; + myOlds = theOlds; + myIsGenerated = isGenerated; + updateSubs(theThisShape, true); + myAlgo.reset(); + myOlds.clear(); +} + + bool Model_ResultBody::isConnectedTopology() { TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); @@ -339,3 +340,19 @@ void Model_ResultBody::cleanCash() aSub->cleanCash(); } } + +void Model_ResultBody::computeOldForSub( + const GeomShapePtr& theSubShape, std::list& theOldForSub) +{ + std::list::iterator aRootOlds = myOlds.begin(); + for(; aRootOlds != myOlds.end(); aRootOlds++) { + ListOfShape aNews; + myIsGenerated ? myAlgo->generated(*aRootOlds, aNews) : myAlgo->modified(*aRootOlds, aNews); + for(ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) { + if (theSubShape->isSame(*aNewIter)) { // found old that was used for new theSubShape creation + theOldForSub.push_back(*aRootOlds); + break; + } + } + } +} diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index 09824971f..e34d1989b 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -43,6 +43,12 @@ class Model_ResultBody : public ModelAPI_ResultBody std::map mySubsMap; /// Keeps the last state of the concealment flag in order to update it when needed. bool myLastConcealed; + /// History information for update subs + std::shared_ptr myAlgo; + /// All old shapes used for the root result construction + std::list myOlds; + /// Information about the kind of the history information: modified or generated + bool myIsGenerated; public: @@ -109,9 +115,17 @@ protected: void updateSubs(const std::shared_ptr& theThisShape, const bool theShapeChanged = true); + /// Updates the sub-bodies in accordance to the algorithm history information + void updateSubs( + const GeomShapePtr& theThisShape, const std::list& theOlds, + const std::shared_ptr theMakeShape, const bool isGenerated); + // Checks the state of children and parents to send events of creation/erase when needed void updateConcealment(); + /// Adds to theOldForSub only old shapes that where used for theSubShape creation + void computeOldForSub(const GeomShapePtr& theSubShape, std::list& theOldForSub); + friend class Model_Objects; }; diff --git a/src/ModelAPI/ModelAPI_BodyBuilder.h b/src/ModelAPI/ModelAPI_BodyBuilder.h index f72202360..7fce455c6 100755 --- a/src/ModelAPI/ModelAPI_BodyBuilder.h +++ b/src/ModelAPI/ModelAPI_BodyBuilder.h @@ -47,13 +47,22 @@ public: /// Stores the generated shape (called by the execution method). virtual void storeGenerated(const GeomShapePtr& theFromShape, - const GeomShapePtr& theToShape) = 0; + const GeomShapePtr& theToShape, + const bool theIsCleanStored = true) = 0; + + /// Stores the root generated shapes (called by the execution method). + virtual void storeGenerated(const std::list& theFromShapes, + const GeomShapePtr& theToShape, const std::shared_ptr theMakeShape) = 0; /// Stores the modified shape (called by the execution method). virtual void storeModified(const GeomShapePtr& theOldShape, const GeomShapePtr& theNewShape, const bool theIsCleanStored = true) = 0; + /// Stores the root modified shapes (called by the execution method). + virtual void storeModified(const std::list& theOldShapes, + const GeomShapePtr& theNewShape, const std::shared_ptr theMakeShape)=0; + /// Returns the shape-result produced by this feature virtual GeomShapePtr shape() = 0; diff --git a/src/ModelAPI/ModelAPI_ResultBody.cpp b/src/ModelAPI/ModelAPI_ResultBody.cpp index ab0e703e7..00e6ad9ef 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.cpp +++ b/src/ModelAPI/ModelAPI_ResultBody.cpp @@ -67,6 +67,21 @@ void ModelAPI_ResultBody::storeGenerated(const GeomShapePtr& theFromShape, updateSubs(theToShape); } +void ModelAPI_ResultBody::storeGenerated( + const std::list& theFromShapes, const GeomShapePtr& theToShape, + const std::shared_ptr theMakeShape) +{ + myBuilder->storeGenerated(theFromShapes, theToShape, theMakeShape); + myConnect = ConnectionNotComputed; + + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + aECreator->sendUpdated(data()->owner(), aRedispEvent); + + updateSubs(theToShape, theFromShapes, theMakeShape, true); +} + void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape, const GeomShapePtr& theNewShape, const bool theIsCleanStored) @@ -82,6 +97,21 @@ void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape, updateSubs(theNewShape); } +void ModelAPI_ResultBody::storeModified( + const std::list& theOldShapes, const GeomShapePtr& theNewShape, + const std::shared_ptr theMakeShape) +{ + myBuilder->storeModified(theOldShapes, theNewShape, theMakeShape); + myConnect = ConnectionNotComputed; + + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + aECreator->sendUpdated(data()->owner(), aRedispEvent); + + updateSubs(theNewShape, theOldShapes, theMakeShape, false); +} + GeomShapePtr ModelAPI_ResultBody::shape() { return myBuilder->shape(); diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index 20e0879f2..dc9ed31da 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -102,11 +102,21 @@ public: MODELAPI_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape, const GeomShapePtr& theToShape); + /// Stores the root modified shapes (called by the execution method). + MODELAPI_EXPORT virtual void storeGenerated( + const std::list& theFromShapes, const GeomShapePtr& theToShape, + const std::shared_ptr theMakeShape); + /// Stores the modified shape (called by the execution method). MODELAPI_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape, const GeomShapePtr& theNewShape, const bool theIsCleanStored = true); + /// Stores the root modified shapes (called by the execution method). + MODELAPI_EXPORT virtual void storeModified( + const std::list& theOldShapes, const GeomShapePtr& theNewShape, + const std::shared_ptr theMakeShape); + /// Returns the shape-result produced by this feature MODELAPI_EXPORT virtual GeomShapePtr shape(); @@ -165,6 +175,11 @@ public: MODELAPI_EXPORT virtual void updateSubs(const GeomShapePtr& theThisShape, const bool theShapeChanged = true) = 0; + /// Updates the sub-bodies in accordance to the algorithm history information + MODELAPI_EXPORT virtual void updateSubs( + const GeomShapePtr& theThisShape, const std::list& theOlds, + const std::shared_ptr theMakeShape, const bool isGenerated) = 0; + /// Cleans cash related to the already stored elements MODELAPI_EXPORT virtual void cleanCash() = 0;