#include <TopTools_ListOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+#include <TopoDS_Builder.hxx>
+
+// new shape -> old shapes -> index in the old shape
+typedef NCollection_DataMap<TopoDS_Shape,
+ NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>, TopTools_ShapeMapHasher>
+ MapNewToOld;
+typedef
+ NCollection_DataMap<int, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher> >
+ HistoryMap;
//=================================================================================================
GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape()
: myBuilderType(Unknown),
myDone(false)
{
+ myHist = 0;
+}
+
+GeomAlgoAPI_MakeShape::~GeomAlgoAPI_MakeShape() {
+ if (myHist) {
+ delete (HistoryMap*)myHist;
+ }
}
//=================================================================================================
aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current()));
myMap->bind(aCurrentShape, aCurrentShape);
}
+ myHist = 0;
}
return true ;
}
+bool GeomAlgoAPI_MakeShape::newShapesCollected(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType)
+{
+ if (!myHist)
+ return false;
+ HistoryMap* aHist = (HistoryMap*)myHist;
+ if (!aHist->IsBound(theShapeType))
+ return false;
+ return aHist->Find(theShapeType).IsBound(theWholeOld->impl<TopoDS_Shape>());
+}
+
+void GeomAlgoAPI_MakeShape::collectNewShapes(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType)
+{
+ if (!myHist)
+ myHist = new HistoryMap;
+ HistoryMap* aHist = (HistoryMap*)myHist;
+ if (!aHist->IsBound(theShapeType))
+ aHist->Bind(
+ theShapeType, NCollection_DataMap<TopoDS_Shape, MapNewToOld, TopTools_ShapeMapHasher>());
+ aHist->ChangeFind(theShapeType). // add a new in anyway
+ Bind(theWholeOld->impl<TopoDS_Shape>(), MapNewToOld());
+ MapNewToOld& aCurrent =
+ aHist->ChangeFind(theShapeType).ChangeFind(theWholeOld->impl<TopoDS_Shape>());
+ ListOfShape aNewList;
+ TopTools_MapOfShape aViewed; //avoid same shapes
+ GeomAPI_ShapeExplorer anExp(theWholeOld, GeomAPI_Shape::ShapeType(theShapeType));
+ for(int anIndexInWholeOld = 0; anExp.more(); anExp.next(), anIndexInWholeOld++) {
+ if (!aViewed.Add(anExp.current()->impl<TopoDS_Shape>()))
+ continue;
+ aNewList.clear();
+ modified(anExp.current(), aNewList);
+ for(ListOfShape::iterator aNew = aNewList.begin(); aNew != aNewList.end(); aNew++) {
+ const TopoDS_Shape& aNewShape = (*aNew)->impl<TopoDS_Shape>();
+ if (!aCurrent.IsBound(aNewShape)) {
+ aCurrent.Bind(
+ aNewShape, NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>());
+ }
+ aCurrent.ChangeFind(aNewShape).Bind(anExp.current()->impl<TopoDS_Shape>(), anIndexInWholeOld);
+ }
+ }
+}
+
+static void addAllSubs(const TopoDS_Shape& theNewShape,
+ MapNewToOld& theCurrent, std::map<int, TopoDS_Shape>& theResMap)
+{
+ if (theCurrent.IsBound(theNewShape)) {
+ NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher>::Iterator
+ anOldIter(theCurrent.Find(theNewShape));
+ for(; anOldIter.More(); anOldIter.Next()) {
+ theResMap[anOldIter.Value()] = anOldIter.Key();
+ }
+ }
+
+ TopoDS_Iterator anIter(theNewShape);
+ for(; anIter.More(); anIter.Next()) {
+ //if (anIter.Value().ShapeType() != TopAbs_VERTEX)
+ addAllSubs(anIter.Value(), theCurrent, theResMap); // add recursively
+ }
+}
+
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_MakeShape::oldShapesForNew(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld,
+ std::shared_ptr<GeomAPI_Shape> theNewShape, const int theShapeType)
+{
+ GeomShapePtr aResult(new GeomAPI_Shape);
+ TopoDS_Compound aResComp;
+ TopoDS_Builder aBuilder;
+ aBuilder.MakeCompound(aResComp);
+ aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));
+
+ HistoryMap* aHist = (HistoryMap*)myHist;
+ if (!aHist->IsBound(theShapeType))
+ return aResult; // not found, empty compound
+ const TopoDS_Shape& aWholeOld = theWholeOld->impl<TopoDS_Shape>();
+ if (!aHist->Find(theShapeType).IsBound(aWholeOld))
+ return aResult; // not found, empty compound
+ std::map<int, TopoDS_Shape> aResMap; // map with all results, ordered by index in whole old
+ MapNewToOld& aCurrent = aHist->ChangeFind(theShapeType).ChangeFind(aWholeOld);
+ // we don't know what type of new shapes were produced by the old theShapeType, so, iterate all
+ addAllSubs(theNewShape->impl<TopoDS_Shape>(), aCurrent, aResMap);
+
+ std::map<int, TopoDS_Shape>::iterator anOldIter = aResMap.begin();
+ for(; anOldIter != aResMap.end(); anOldIter++) {
+ if (anOldIter->second.ShapeType() == (TopAbs_ShapeEnum)theShapeType)
+ aBuilder.Add(aResComp, anOldIter->second);
+ }
+ aResult->setImpl<TopoDS_Shape>(new TopoDS_Shape(aResComp));
+ return aResult;
+}
/// \brief Empty constructor.
GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape();
+ /// Destructor for remove myHist
+ GEOMALGOAPI_EXPORT ~GeomAlgoAPI_MakeShape();
+
/// \brief Constructor by builder and builder type.
/// \param[in] theBuilder pointer to the builder.
/// \param[in] theBuilderType builder type.
/// \brief Check the validity of the produced shape.
GEOMALGOAPI_EXPORT bool checkValid(std::string theMessage);
+ /// Optimization of access the new shapes by old shapes for the limited set of needed new shapes.
+ /// \param theWholeOld the whole old shape
+ /// \param theShapeType type of the sub-shapes that is used for optimization
+ /// \returns true if optimization containers are already filled
+ GEOMALGOAPI_EXPORT bool newShapesCollected(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType);
+
+ /// Optimization of access the new shapes by old shapes for the limited set of needed new shapes.
+ /// \param theWholeOld the whole old shape
+ /// \param theShapeType type of the sub-shapes that is used for optimization
+ /// \returns true if optimization containers are already filled
+ GEOMALGOAPI_EXPORT void collectNewShapes(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld, const int theShapeType);
+
+ /// Optimization of access the new shapes by old shapes for the limited set of needed new shapes.
+ /// \param theWholeOld the whole old shape
+ /// \param theNewShape the whole new shape
+ /// \param theShapeType type of the old sub-shapes
+ /// \returns compound of all old shapes that were used for creation of the given new
+ GEOMALGOAPI_EXPORT std::shared_ptr<GeomAPI_Shape> oldShapesForNew(
+ std::shared_ptr<GeomAPI_Shape> theWholeOld,
+ std::shared_ptr<GeomAPI_Shape> theNewShape, const int theShapeType);
+
protected:
/// \brief Sets builder type.
/// \param[in] theBuilderType new builder type.
GeomAlgoAPI_MakeShape::BuilderType myBuilderType; ///< Type of make shape builder.
bool myDone; ///< Builder status.
std::shared_ptr<GeomAPI_Shape> myShape; ///< Resulting shape.
+
+ /// map that is used to keep the optimization structure for access to the history
+ /// kind of sub-shapes -> whole old shape -> new shape -> list of old shapes that create this new
+ void* myHist;
};
typedef std::list<std::shared_ptr<GeomAlgoAPI_MakeShape> > ListOfMakeShape;
}
void Model_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
- std::shared_ptr<GeomAPI_Shape> theShapeIn, const int theKindOfShape, const int theTag,
+ 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)
{
if (theSplitInSubs && mySubs.size()) { // consists of subs
+ // optimization of getting of new shapes for specific sub-result
+ if (!theMS->newShapesCollected(theShapeIn, theKindOfShape))
+ theMS->collectNewShapes(theShapeIn, theKindOfShape);
std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
for(; aSubIter != mySubs.cend(); aSubIter++) {
// check that sub-shape was also created as modification of ShapeIn