+ myAlgo = theMakeShape;
+ myOlds = theOlds;
+ myIsGenerated = isGenerated;
+ // to avoid changing of "isDisabled" flag in the "updateSubs" cycle
+ isDisabled();
+
+ updateSubs(theThisShape, true);
+ myAlgo.reset();
+ myOlds.clear();
+ myHistoryCash.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();
+ }
+}
+
+// adds to the theSubSubs map all sub-shapes of theSub if it is compound of compsolid
+static void collectSubs(
+ const GeomShapePtr theSub, TopTools_MapOfShape& theSubSubs, const bool theOneLevelMore)
+{
+ if (theSub->isNull())
+ return;
+ if (theSubSubs.Add(theSub->impl<TopoDS_Shape>())) {
+ bool aIsComp = theSub->isCompound() || theSub->isCompSolid();
+ if (aIsComp) {
+ for(GeomAPI_ShapeIterator anIter(theSub); anIter.more(); anIter.next())
+ collectSubs(anIter.current(), theSubSubs, theOneLevelMore);
+ } else if (theOneLevelMore) {
+ GeomAPI_Shape::ShapeType aSubType = GeomAPI_Shape::ShapeType(int(theSub->shapeType()) + 1);
+ if (aSubType == GeomAPI_Shape::SHAPE)
+ return;
+ if (aSubType == GeomAPI_Shape::SHELL)
+ aSubType = GeomAPI_Shape::FACE;
+ if (aSubType == GeomAPI_Shape::WIRE)
+ aSubType = GeomAPI_Shape::EDGE;
+
+ for(GeomAPI_ShapeExplorer anExp(theSub, aSubType); anExp.more(); anExp.next()) {
+ collectSubs(anExp.current(), theSubSubs, false);
+ }
+ }
+ }
+}
+
+void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
+ const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
+{
+ // the old can be also used for sub-shape of theSub; collect all subs of compound or compsolid
+ TopTools_MapOfShape aSubSubs;
+ collectSubs(theSub, aSubSubs, false);
+
+ std::list<GeomShapePtr>::const_iterator aRootOlds = theAllOlds.cbegin();
+ for (; aRootOlds != theAllOlds.cend(); aRootOlds++) {
+ // use sub-shapes of olds too if they are compounds or compsolids
+ TopTools_MapOfShape anOldSubs;
+ // iterate one level more (for intersection of solids this is face)
+ collectSubs(*aRootOlds, anOldSubs, true);
+ for (TopTools_MapOfShape::Iterator anOldIter(anOldSubs); anOldIter.More(); anOldIter.Next()) {
+ TopoDS_Shape anOldShape = anOldIter.Value();
+ if (anOldShape.ShapeType() == TopAbs_COMPOUND || anOldShape.ShapeType() == TopAbs_SHELL ||
+ anOldShape.ShapeType() == TopAbs_WIRE)
+ continue; // container old-shapes are not supported by the history, may cause crash
+ GeomShapePtr anOldSub(new GeomAPI_Shape);
+ anOldSub->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOldShape));
+
+ ListOfShape aNews;
+ if (myHistoryCash.IsBound(anOldShape)) {
+ const TopTools_ListOfShape& aList = myHistoryCash.Find(anOldShape);
+ for(TopTools_ListIteratorOfListOfShape anIter(aList); anIter.More(); anIter.Next()) {
+ GeomShapePtr aShape(new GeomAPI_Shape);
+ aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(anIter.Value()));
+ aNews.push_back(aShape);
+ }
+ } else {
+ myIsGenerated ? myAlgo->generated(anOldSub, aNews) : myAlgo->modified(anOldSub, aNews);
+ // MakeShape may return alone old shape if there is no history information for this input
+ if (aNews.size() == 1 && aNews.front()->isEqual(anOldSub))
+ aNews.clear();
+ // store result in the history
+ TopTools_ListOfShape aList;
+ for (ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+ aList.Append((*aNewIter)->impl<TopoDS_Shape>());
+ }
+ myHistoryCash.Bind(anOldShape, aList);
+ }
+
+ for (ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+ if (aSubSubs.Contains((*aNewIter)->impl<TopoDS_Shape>())) {
+ // check list already contains this sub
+ std::list<GeomShapePtr>::iterator aResIter = theOldForSub.begin();
+ for(; aResIter != theOldForSub.end(); aResIter++)
+ if ((*aResIter)->isSame(anOldSub))
+ break;
+ if (aResIter == theOldForSub.end())
+ theOldForSub.push_back(anOldSub); // found old used for new theSubShape creation
+ break;
+ }
+ }