X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_ResultBody.cpp;h=9b3401290035a5711ffe328a4c91bb532f270801;hb=5fb6a80c4e86e21b1181b4e6ee940d946b5c52e4;hp=2a82cc445e47b129595ced1a6212f4c6b9b1acd7;hpb=5a82acff74697623112b76b67c0200945a3e9976;p=modules%2Fshaper.git diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 2a82cc445..9b3401290 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -27,11 +27,17 @@ #include #include #include +#include #include #include #include +#include +// if this attribute exists, the shape is connected topology +Standard_GUID kIsConnectedTopology("e51392e0-3a4d-405d-8e36-bbfe19858ef5"); +// if this attribute exists, the connected topology flag must be recomputed +Standard_GUID kUpdateConnectedTopology("01ef7a45-0bec-4266-b0b4-4aa570921818"); Model_ResultBody::Model_ResultBody() : ModelAPI_ResultBody() { @@ -77,11 +83,12 @@ void Model_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS, }*/ (*aSubIter)->loadAndOrientModifiedShapes( theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate, - theIsStoreAsGenerated); + theIsStoreAsGenerated, theSplitInSubs); } } else { // do for this directly - myBuilder->loadAndOrientGeneratedShapes( - theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes); + myBuilder->loadAndOrientModifiedShapes( + theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate, + theIsStoreAsGenerated); } } @@ -92,6 +99,8 @@ int Model_ResultBody::numberOfSubs(bool forTree) const ResultBodyPtr Model_ResultBody::subResult(const int theIndex, bool forTree) const { + if (theIndex >= int(mySubs.size())) + return ResultBodyPtr(); return mySubs.at(theIndex); } @@ -118,7 +127,7 @@ bool Model_ResultBody::setDisabled(std::shared_ptr theThis, con bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag); if (aChanged) { // state is changed, so modifications are needed myBuilder->evolutionToSelection(theFlag); - updateSubs(shape()); // to set disabled/enabled + updateSubs(shape(), false); // to set disabled/enabled } return aChanged; } @@ -136,69 +145,73 @@ void Model_ResultBody::setIsConcealed(const bool theValue) } } +// recursively check all subs for concealment flag, returns true if everybody have "flag" state, +// in theAll returns results with "flag" state +static bool checkAllSubs(ResultBodyPtr theParent, bool theFlag, std::list& theAll) +{ + if (theParent->isConcealed() != theFlag) + theAll.push_back(theParent); + bool aResult = theParent->ModelAPI_ResultBody::isConcealed() == theFlag; + for(int a = 0; a < theParent->numberOfSubs(); a++) { + bool aSubRes = checkAllSubs(theParent->subResult(a), theFlag, theAll); + if (theFlag) + aResult = aResult || aSubRes; // concealed: one makes concealed everyone + else + aResult = aResult && aSubRes; // not concealed: all must be not concealed + } + return aResult; +} + void Model_ResultBody::updateConcealment() { if (myLastConcealed != ModelAPI_ResultBody::isConcealed()) { - ResultPtr anOwner = std::dynamic_pointer_cast(data()->owner()); - std::shared_ptr aParent = std::dynamic_pointer_cast( - ModelAPI_Tools::bodyOwner(anOwner)); - - myLastConcealed = ModelAPI_ResultBody::isConcealed(); // set new value and check parent - if (myLastConcealed) { // this becomes concealed, so, update all: parent and children - if (aParent.get()) - aParent->updateConcealment(); - static Events_ID EVENT_DISP = - Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendDeleted(document(), groupName()); - ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), EVENT_DISP); - std::vector::const_iterator aSubIter = mySubs.cbegin(); - for (; aSubIter != mySubs.cend(); aSubIter++) { - std::dynamic_pointer_cast(*aSubIter)->updateConcealment(); - } - } else { - // ask parent: if it is still concealed, nothing is changed - if (aParent.get()) { - aParent->updateConcealment(); - if (aParent->isConcealed()) { - myLastConcealed = true; - return; - } - } - // iterate children: if they are concealed, nothing is changed - bool aChildConcealed = false; - std::vector::const_iterator aSubIter = mySubs.cbegin(); - for (; aSubIter != mySubs.cend(); aSubIter++) { - std::dynamic_pointer_cast(*aSubIter)->updateConcealment(); - if ((*aSubIter)->isConcealed()) { - aChildConcealed = true; - break; - } - } - if (aChildConcealed) { // some child is concealed, so, update back - myLastConcealed = true; - if (aParent.get()) - aParent->updateConcealment(); - std::vector::const_iterator aSubIter = mySubs.cbegin(); - for (; aSubIter != mySubs.cend(); aSubIter++) { - std::dynamic_pointer_cast(*aSubIter)->updateConcealment(); + // check the whole tree of results: if one is concealed, everybody are concealed + ResultBodyPtr anOwner = std::dynamic_pointer_cast(data()->owner()); + if (!anOwner.get()) + return; // "this" is invalid + ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(anOwner); + while(aParent.get()) { + anOwner = aParent; + aParent = ModelAPI_Tools::bodyOwner(anOwner); + } + // iterate all results and collect all results whose state may be updated + std::list anUpdated; + bool aNewFlag = !myLastConcealed; + if (checkAllSubs(anOwner, aNewFlag, anUpdated)) { // state of everyone must be updated + std::list::iterator aRes = anUpdated.begin(); + for(; aRes != anUpdated.end(); aRes++) { + bool aLastConcealed = (*aRes)->isConcealed(); + if (aNewFlag != aLastConcealed) { + std::dynamic_pointer_cast(*aRes)->myLastConcealed = aNewFlag; + if (aNewFlag) { // become concealed, behaves like removed + ModelAPI_EventCreator::get()->sendDeleted(document(), groupName()); + } else { // become not-concealed, behaves like created + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(*aRes, anEvent); + } + static Events_ID EVENT_DISP = // must be redisplayed in any case + Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(*aRes, EVENT_DISP); } - } else { // so, it becomes unconcealed - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent); - static Events_ID EVENT_DISP = - Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); - ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), EVENT_DISP); } } } } -void Model_ResultBody::updateSubs(const std::shared_ptr& theThisShape) +void Model_ResultBody::updateSubs(const std::shared_ptr& theThisShape, + const bool theShapeChanged) { static Events_Loop* aLoop = Events_Loop::loop(); static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); static Events_ID EVENT_UPD = aLoop->eventByName(EVENT_OBJECT_UPDATED); static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + // erase flag that topology is connected: the shape is new + if (theShapeChanged && data().get()) { + TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); + if (!aDataLab.IsNull()) { + TDataStd_UAttribute::Set(aDataLab, kUpdateConnectedTopology); + } + } // iterate all sub-solids of compsolid to make sub-results synchronized with them TopoDS_Shape aThisShape; if (theThisShape.get()) aThisShape = theThisShape->impl(); @@ -216,6 +229,10 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS aSub = anObjects->createBody(this->data(), aSubIndex); mySubs.push_back(aSub); mySubsMap[aSub] = int(mySubs.size() - 1); + if (isConcealed()) { // for issue #2579 note7 + aSub->ModelAPI_ResultBody::setIsConcealed(true); + std::dynamic_pointer_cast(aSub)->updateConcealment(); + } } else { // just update shape of this result aSub = mySubs[aSubIndex]; } @@ -229,8 +246,10 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS // erase left, unused results while(mySubs.size() > aSubIndex) { ResultBodyPtr anErased = *(mySubs.rbegin()); - if (anErased->ModelAPI_ResultBody::isConcealed()) + if (anErased->ModelAPI_ResultBody::isConcealed()) { + anErased->ModelAPI_ResultBody::setIsConcealed(false); std::dynamic_pointer_cast(anErased)->updateConcealment(); + } anErased->setDisabled(anErased, true); mySubsMap.erase(anErased); mySubs.pop_back(); @@ -242,8 +261,10 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS } else if (!mySubs.empty()) { // erase all subs while(!mySubs.empty()) { ResultBodyPtr anErased = *(mySubs.rbegin()); - if (anErased->ModelAPI_ResultBody::isConcealed()) + if (anErased->ModelAPI_ResultBody::isConcealed()) { + anErased->ModelAPI_ResultBody::setIsConcealed(false); std::dynamic_pointer_cast(anErased)->updateConcealment(); + } anErased->setDisabled(anErased, true); // even if it is invalid (to erase subs on abort/undo) mySubs.pop_back(); } @@ -266,3 +287,21 @@ bool Model_ResultBody::isLatestEqual(const std::shared_ptr& theSh } return false; } + +bool Model_ResultBody::isConnectedTopology() +{ + TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); + if (!aDataLab.IsNull()) { + if (aDataLab.IsAttribute(kUpdateConnectedTopology)) { // recompute state + aDataLab.ForgetAttribute(kUpdateConnectedTopology); + GeomShapePtr aShape = shape(); + if (aShape.get() && aShape->isConnectedTopology()) { + TDataStd_UAttribute::Set(aDataLab, kIsConnectedTopology); + } else { + aDataLab.ForgetAttribute(kIsConnectedTopology); + } + } + return aDataLab.IsAttribute(kIsConnectedTopology); + } + return false; // invalid case +}