#include <ModelAPI_Object.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Tools.h>
+#include <Model_Data.h>
#include <Events_Loop.h>
+#include <GeomAPI_ShapeIterator.h>
#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
+#include <TDataStd_UAttribute.hxx>
+// 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()
{
delete myBuilder;
}
-void Model_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
- std::shared_ptr<GeomAPI_Shape> theShapeIn, const int theKindOfShape, const int theTag,
- const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
- const bool theIsStoreSeparate,
- const bool theIsStoreAsGenerated,
- const bool theSplitInSubs)
+bool Model_ResultBody::generated(const GeomShapePtr& theNewShape,
+ const std::string& theName, const bool theCheckIsInResult)
{
- if (theSplitInSubs && mySubs.size()) { // consists of subs
+ bool aResult = false;
+ if (mySubs.size()) { // consists of subs
+ for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+ aSubIter != mySubs.cend();
+ ++aSubIter)
+ {
+ const ResultBodyPtr& aSub = *aSubIter;
+ if (aSub->generated(theNewShape, theName, theCheckIsInResult))
+ aResult = true;
+ }
+ } else { // do for this directly
+ if (myBuilder->generated(theNewShape, theName, theCheckIsInResult))
+ aResult = true;
+ }
+ return aResult;
+}
+
+void Model_ResultBody::loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
+ const GeomShapePtr& theOldShape,
+ const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
+ const std::string& theName)
+{
+ if (mySubs.size()) { // consists of subs
+ for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+ aSubIter != mySubs.cend();
+ ++aSubIter)
+ {
+ const ResultBodyPtr& aSub = *aSubIter;
+ aSub->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+ }
+ } else { // do for this directly
+ myBuilder->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+ }
+}
+
+void Model_ResultBody::loadModifiedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
+ const GeomShapePtr& theOldShape,
+ const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
+ const std::string& theName)
+{
+ if (mySubs.size()) { // consists of subs
+ // optimization of getting of new shapes for specific sub-result
+ if (!theAlgo->isNewShapesCollected(theOldShape, theShapeTypeToExplore))
+ theAlgo->collectNewShapes(theOldShape, theShapeTypeToExplore);
std::vector<ResultBodyPtr>::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>();
- TopoDS_Shape aWholeIn = theShapeIn->impl<TopoDS_Shape>();
- for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) {
- ListOfShape aHistory;
- std::shared_ptr<GeomAPI_Shape> aSubIn(new GeomAPI_Shape());
- aSubIn->setImpl((new TopoDS_Shape(anExp.Current())));
- theMS->modified(aSubIn, aHistory);
- std::list<std::shared_ptr<GeomAPI_Shape> >::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)->loadAndOrientModifiedShapes(
- theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
- theIsStoreAsGenerated, theSplitInSubs);
+ (*aSubIter)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
}
} else { // do for this directly
- myBuilder->loadAndOrientModifiedShapes(
- theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
- theIsStoreAsGenerated);
+ myBuilder->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
}
}
ResultBodyPtr Model_ResultBody::subResult(const int theIndex, bool forTree) const
{
+ if (theIndex >= int(mySubs.size()))
+ return ResultBodyPtr();
return mySubs.at(theIndex);
}
{
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;
}
if (myLastConcealed != ModelAPI_ResultBody::isConcealed()) {
// check the whole tree of results: if one is concealed, everybody are concealed
ResultBodyPtr anOwner = std::dynamic_pointer_cast<ModelAPI_ResultBody>(data()->owner());
+ if (!anOwner.get())
+ return; // "this" is invalid
ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(anOwner);
while(aParent.get()) {
anOwner = aParent;
}
}
-void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape)
+void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& 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<Model_Data>(data())->label();
+ if (!aDataLab.IsNull()) {
+ TDataStd_UAttribute::Set(aDataLab, kUpdateConnectedTopology);
+ isConnectedTopology(); // to store this flag in transaction, #2630
+ }
+ }
// iterate all sub-solids of compsolid to make sub-results synchronized with them
TopoDS_Shape aThisShape;
if (theThisShape.get()) aThisShape = theThisShape->impl<TopoDS_Shape>();
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<Model_ResultBody>(aSub)->updateConcealment();
+ }
} else { // just update shape of this result
aSub = mySubs[aSubIndex];
}
- if (!aShape->isEqual(aSub->shape())) {
- aSub->store(aShape, false);
+ GeomShapePtr anOldSubShape = aSub->shape();
+ if (!aShape->isEqual(anOldSubShape)) {
+ if (myAlgo.get()) {
+ std::list<GeomShapePtr> anOldForSub;
+ computeOldForSub(aShape, myOlds, 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);
}
// redisplay this because result with and without subs are displayed differently
aECreator->sendUpdated(data()->owner(), EVENT_DISP);
}
+ cleanCash();
} else if (!mySubs.empty()) { // erase all subs
while(!mySubs.empty()) {
ResultBodyPtr anErased = *(mySubs.rbegin());
}
}
-bool Model_ResultBody::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
+void Model_ResultBody::updateSubs(
+ const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+ const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated)
{
- if (myBuilder->isLatestEqual(theShape))
- return true;
- // also check that it is asked for sub-elements
- std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
- for(; aSubIter != mySubs.cend(); aSubIter++) {
- if (aSubIter->get() && (*aSubIter)->isLatestEqual(theShape)) {
- return true;
+ myAlgo = theMakeShape;
+ myOlds = theOlds;
+ myIsGenerated = isGenerated;
+ updateSubs(theThisShape, true);
+ myAlgo.reset();
+ myOlds.clear();
+}
+
+
+bool Model_ResultBody::isConnectedTopology()
+{
+ TDF_Label aDataLab = std::dynamic_pointer_cast<Model_Data>(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
+}
+
+void Model_ResultBody::cleanCash()
+{
+ myBuilder->cleanCash();
+ for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+ aSubIter != mySubs.cend(); ++aSubIter)
+ {
+ const ResultBodyPtr& aSub = *aSubIter;
+ aSub->cleanCash();
+ }
+}
+
+void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
+ const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
+{
+ std::list<GeomShapePtr>::const_iterator aRootOlds = theAllOlds.cbegin();
+ for(; aRootOlds != theAllOlds.cend(); aRootOlds++) {
+ ListOfShape aNews;
+ myIsGenerated ? myAlgo->generated(*aRootOlds, aNews) : myAlgo->modified(*aRootOlds, aNews);
+ // MakeShape may return alone old shape if there is no history information for this input
+ if (aNews.size() == 1 && aNews.front()->isEqual(*aRootOlds))
+ aNews.clear();
+ if (aNews.empty()) { // try to iterate to sub-elements (for intersection of solids this is face)
+ std::list<GeomShapePtr> theAllSubOlds;
+ for(GeomAPI_ShapeIterator aSubOld(*aRootOlds); aSubOld.more(); aSubOld.next()) {
+ GeomShapePtr aSub = aSubOld.current();
+ if (aSub.get() && !aSub->isNull())
+ theAllSubOlds.push_back(aSub);
+ }
+ computeOldForSub(theSub, theAllSubOlds, theOldForSub);
+ }
+ for(ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+ if (theSub->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
+ theOldForSub.push_back(*aRootOlds);
+ break;
+ }
}
}
- return false;
}