X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_BodyBuilder.cpp;h=a0f074c755aaad0c2f3d656d4c523388595490f1;hb=c57b0044525edb117d2b10cca0a931eecb5681f5;hp=4209b2401ccbf509f25e120e8ecc6a8fc593d574;hpb=1e1b7ad082844bc8bdbbd002ae8ca1c0c7e5010f;p=modules%2Fshaper.git diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 4209b2401..a0f074c75 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -22,17 +22,21 @@ #include #include +#include #include #include #include #include +#include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -47,89 +51,128 @@ #include #include #include +#include #include +#include #include +#include #include // DEB //#include -//#include //#define DEB_IMPORT 1 +/// reference to the shape in external document: sting list attribute identifier +static const Standard_GUID kEXTERNAL_SHAPE_REF("9aa5dd14-6d34-4a8d-8786-05842fd7bbbd"); + +static const int INVALID_TAG = -1; +static const int GENERATED_VERTICES_TAG = 1; +static const int GENERATED_EDGES_TAG = 2; +static const int GENERATED_FACES_TAG = 3; +static const int MODIFIED_VERTICES_TAG = 4; +static const int MODIFIED_EDGES_TAG = 5; +static const int MODIFIED_FACES_TAG = 6; +static const int DELETED_TAG = 7; +static const int PRIMITIVES_START_TAG = 11; + +static int getGenerationTag(const TopoDS_Shape& theShape) { + TopAbs_ShapeEnum aShapeType = theShape.ShapeType(); + switch (aShapeType) { + case TopAbs_VERTEX: return GENERATED_VERTICES_TAG; + case TopAbs_EDGE: return GENERATED_EDGES_TAG; + case TopAbs_FACE: return GENERATED_FACES_TAG; + } + + return INVALID_TAG; +} + +static int getModificationTag(const TopoDS_Shape& theShape) { + TopAbs_ShapeEnum aShapeType = theShape.ShapeType(); + switch (aShapeType) { + case TopAbs_VERTEX: return MODIFIED_VERTICES_TAG; + case TopAbs_EDGE: return MODIFIED_EDGES_TAG; + case TopAbs_FACE: return MODIFIED_FACES_TAG; + } + + return INVALID_TAG; +} + +static bool isAlreadyStored(const TNaming_Builder* theBuilder, + const TopoDS_Shape& theOldShape, + const TopoDS_Shape& theNewShape) +{ + for (TNaming_Iterator aNamingIt(theBuilder->NamedShape()); + aNamingIt.More(); + aNamingIt.Next()) + { + if (aNamingIt.NewShape().IsSame(theNewShape) + && aNamingIt.OldShape().IsSame(theOldShape)) + { + return true; + } + } + + return false; +} + Model_BodyBuilder::Model_BodyBuilder(ModelAPI_Object* theOwner) -: ModelAPI_BodyBuilder(theOwner) +: ModelAPI_BodyBuilder(theOwner), + myFreePrimitiveTag(PRIMITIVES_START_TAG) { } -// Converts evolution of naming shape to selection evelution and back to avoid -// naming support on the disabled results. Deeply in the labels tree, recursively. -static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) { - std::list > aShapePairs; // to store old and new shapes - Handle(TNaming_NamedShape) aName; - int anEvolution = -1; - if (theLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { - TNaming_Evolution aNSEvol = aName->Evolution(); - if ((aNSEvol == TNaming_SELECTED && theFlag) || - (aNSEvol != TNaming_SELECTED && !theFlag)) { // nothing to do, it is already correct - return; - } - anEvolution = (int)(aNSEvol); - if (!theFlag) { - Handle(TDataStd_Integer) anAttrEvol; - if (theLab.FindAttribute(TDataStd_Integer::GetID(), anAttrEvol)) { - anEvolution = anAttrEvol->Get(); - } - } else { - TDataStd_Integer::Set(theLab, anEvolution); - } - - for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) { - // iterator goes in reversed order relatively to the Builder, to, make the list reversed - aShapePairs.push_front(std::pair - (anIter.OldShape(), anIter.NewShape())); - } - - // create new - TNaming_Builder aBuilder(theLab); - TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution); - std::list >::iterator aPairsIter = aShapePairs.begin(); - for(; aPairsIter != aShapePairs.end(); aPairsIter++) { - if (theFlag) { // disabled => make selection - aBuilder.Select(aPairsIter->second, aPairsIter->first); - } else if (anEvol == TNaming_GENERATED) { - aBuilder.Generated(aPairsIter->first, aPairsIter->second); - } else if (anEvol == TNaming_MODIFY) { - aBuilder.Modify(aPairsIter->first, aPairsIter->second); - } else if (anEvol == TNaming_DELETE) { - aBuilder.Delete(aPairsIter->first); - } else if (anEvol == TNaming_PRIMITIVE) { - aBuilder.Generated(aPairsIter->second); - } else if (anEvol == TNaming_SELECTED) { - aBuilder.Select(aPairsIter->second, aPairsIter->first); +/// Checks that shape is presented in the tree with not-selection evolution +/// In theOriginalLabel it returns label where NS of old sub-shape is stored +static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2, + TopoDS_Shape theShape, TDF_Label& theOriginalLabel) +{ + bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape); + if (aResult) { //check evolution and a label of this shape + for(TNaming_SameShapeIterator aShapes(theShape, theAccess1); aShapes.More(); aShapes.Next()) + { + static Handle(TNaming_NamedShape) aNS; + if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aNS->Evolution() != TNaming_SELECTED) { + theOriginalLabel = aNS->Label(); + return true; + } } } } - // recursive call for all sub-labels - TDF_ChildIterator anIter(theLab, Standard_False); - for(; anIter.More(); anIter.Next()) { - evolutionToSelectionRec(anIter.Value(), theFlag); + if (!theAccess2.IsNull()) { + static const TDF_Label anEmpty; + return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel); } + return false; } -void Model_BodyBuilder::evolutionToSelection(const bool theFlag) +/// Stores entry to the external label in the entries list at this label +static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (!aData) // unknown case - return; - TDF_Label& aShapeLab = aData->shapeLab(); - evolutionToSelectionRec(aShapeLab, theFlag); + // store information about the external document reference to restore old shape on open + if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) { + Handle(TDataStd_ExtStringList) anEntries; + if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) { + anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF); + } + TCollection_AsciiString anEntry; + TDF_Tool::Entry(theExternal, anEntry); + // check it already contains this entry + TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List()); + for(; anIter.More(); anIter.Next()) + if (anIter.Value() == anEntry) + break; + if (!anIter.More()) { + anEntries->Append(anEntry); + } + } } -void Model_BodyBuilder::store(const std::shared_ptr& theShape, +void Model_BodyBuilder::store(const GeomShapePtr& theShape, const bool theIsStoreSameShapes) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); + TDF_Label aShapeLab = aData->shapeLab(); // clean builders clean(); // store the new shape as primitive @@ -142,7 +185,8 @@ void Model_BodyBuilder::store(const std::shared_ptr& theShape, if(!theIsStoreSameShapes) { Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aShape, aShapeLab); - if(!aNS.IsNull() && !aNS->IsEmpty()) { + // the last condition is for the issue 2751 : existing shape may be found in compound-NS + if(!aNS.IsNull() && !aNS->IsEmpty() && aNS->Get().IsSame(aShape)) { // This shape is already in document, store reference instead of shape; const TDF_Label aFoundLabel = aNS->Label(); TDF_Reference::Set(aShapeLab, aFoundLabel); @@ -168,16 +212,16 @@ void Model_BodyBuilder::store(const std::shared_ptr& theShape, } } -void Model_BodyBuilder::storeGenerated(const std::shared_ptr& theFromShape, - const std::shared_ptr& theToShape) +void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape, + const GeomShapePtr& theToShape, const bool theIsCleanStored) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); + TDF_Label aShapeLab = aData->shapeLab(); // clean builders - clean(); - // store the new shape as primitive - TNaming_Builder aBuilder(aShapeLab); + if (theIsCleanStored) + clean(); + TNaming_Builder* aBuilder = builder(0); if (!theFromShape || !theToShape) return; // bad shape TopoDS_Shape aShapeBasis = theFromShape->impl(); @@ -186,32 +230,87 @@ void Model_BodyBuilder::storeGenerated(const std::shared_ptr& the TopoDS_Shape aShapeNew = theToShape->impl(); if (aShapeNew.IsNull()) return; // null shape inside - aBuilder.Generated(aShapeBasis, aShapeNew); + + // There is no sense to write history if old shape does not exist in the document. + TDF_Label anAccess2 = std::dynamic_pointer_cast( + ModelAPI_Session::get()->moduleDocument())->generalLabel(); + TDF_Label anOriginalLabel; + if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeBasis, anOriginalLabel)) { + if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway + aBuilder->Generated(aShapeNew); + } + } else { + if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before + myBuilders.erase(0); + aBuilder = builder(0); + } + + aBuilder->Generated(aShapeBasis, aShapeNew); + // store information about the external document reference to restore old shape on open + storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label()); + } + // register name - if(!aBuilder.NamedShape()->IsEmpty()) { + 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 = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); + aDoc->addNamingName(aBuilder->NamedShape()->Label(), aName); } } } } } -void Model_BodyBuilder::storeModified(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape, const int theDecomposeSolidsTag) +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); + if (aFind == myBuilders.end()) { + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + myBuilders[theTag] = new TNaming_Builder( + theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag)); + aFind = myBuilders.find(theTag); + } + return aFind->second; +} + +void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape, + const GeomShapePtr& theNewShape, + const bool theIsCleanStored) { std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); // clean builders - clean(); - // store the new shape as primitive - TNaming_Builder aBuilder(aShapeLab); + if (theIsCleanStored) clean(); + TNaming_Builder* aBuilder = builder(0); if (!theOldShape || !theNewShape) return; // bad shape TopoDS_Shape aShapeOld = theOldShape->impl(); @@ -220,33 +319,62 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr& theO TopoDS_Shape aShapeNew = theNewShape->impl(); if (aShapeNew.IsNull()) return; // null shape inside - aBuilder.Modify(aShapeOld, aShapeNew); - if(!aBuilder.NamedShape()->IsEmpty()) { + + // There is no sense to write history if old shape does not exist in the document. + TDF_Label anAccess2 = std::dynamic_pointer_cast( + ModelAPI_Session::get()->moduleDocument())->generalLabel(); + TDF_Label anOriginalLabel; + if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeOld, anOriginalLabel)) { + if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway + aBuilder->Generated(aShapeNew); + } + } else { + if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before + myBuilders.erase(0); + aBuilder = builder(0); + } + + aBuilder->Modify(aShapeOld, aShapeNew); + // store information about the external document reference to restore old shape on open + storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label()); + } + + 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 = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); + aDoc->addNamingName(aBuilder->NamedShape()->Label(), aName); } } } } } -void Model_BodyBuilder::storeWithoutNaming(const std::shared_ptr& theShape) +void Model_BodyBuilder::storeModified(const std::list& theOldShapes, + const GeomShapePtr& theNewShape, const std::shared_ptr theMakeShape) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - clean(); - if (!theShape.get()) - return; // bad shape - TopoDS_Shape aShape = theShape->impl(); - if (aShape.IsNull()) - return; // null shape inside - TNaming_Builder aBuilder(aData->shapeLab()); - aBuilder.Select(aShape, aShape); + 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; } } @@ -257,229 +385,327 @@ void Model_BodyBuilder::clean() return; std::map::iterator aBuilder = myBuilders.begin(); for(; aBuilder != myBuilders.end(); aBuilder++) { + Handle(TNaming_NamedShape) aNS = aBuilder->second->NamedShape(); delete aBuilder->second; - // clear also shapes on cleaned sub-labels (#2241) - Handle(TNaming_NamedShape) aNS; - if (aLab.FindChild(aBuilder->first).FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - aNS->Clear(); - } + if (!aNS.IsNull() && !aNS->Label().IsNull()) + aNS->Label().ForgetAttribute(TNaming_NamedShape::GetID()); } myBuilders.clear(); + myPrimitivesNamesIndexMap.clear(); + // remove the old reference (if any) + aLab.ForgetAttribute(TDF_Reference::GetID()); + myFreePrimitiveTag = PRIMITIVES_START_TAG; + TDF_ChildIDIterator anEntriesIter(aLab, kEXTERNAL_SHAPE_REF, true); + for(; anEntriesIter.More(); anEntriesIter.Next()) { + anEntriesIter.Value()->Label().ForgetAttribute(kEXTERNAL_SHAPE_REF); + } } -Model_BodyBuilder::~Model_BodyBuilder() +void Model_BodyBuilder::cleanCash() { - clean(); + myPrimitivesNamesIndexMap.clear(); } -TNaming_Builder* Model_BodyBuilder::builder(const int theTag) +Model_BodyBuilder::~Model_BodyBuilder() { - std::map::iterator aFind = myBuilders.find(theTag); - if (aFind == myBuilders.end()) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag)); - aFind = myBuilders.find(theTag); - } - return aFind->second; + clean(); } void Model_BodyBuilder::buildName(const int theTag, const std::string& theName) { - std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - //aDoc->addNamingName(builder(theTag)->NamedShape()->Label(), theName); - TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(), theName.c_str()); + std::string aName = theName; + std::string aPrefix = ""; + switch (theTag) { + case GENERATED_VERTICES_TAG: aPrefix = aName.empty() ? "Generated_Vertex" : "GV:"; break; + case GENERATED_EDGES_TAG: aPrefix = aName.empty() ? "Generated_Edge" : "GE:"; break; + case GENERATED_FACES_TAG: aPrefix = aName.empty() ? "Generated_Face" : "GF:"; break; + case MODIFIED_VERTICES_TAG: aPrefix = aName.empty() ? "Modified_Vertex" : "MV:"; break; + case MODIFIED_EDGES_TAG: aPrefix = aName.empty() ? "Modified_Edge" : "ME:"; break; + case MODIFIED_FACES_TAG: aPrefix = aName.empty() ? "Modified_Face" : "MF:"; break; + } + aName.insert(0, aPrefix); + + TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(), aName.c_str()); } -void Model_BodyBuilder::generated( - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) +bool Model_BodyBuilder::generated(const GeomShapePtr& theNewShape, + const std::string& theName, + const bool theCheckIsInResult) { + GeomShapePtr aResultShape = shape(); + if (theCheckIsInResult) { + bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(theNewShape, false); + if (aNewShapeIsNotInResultShape) { + return false; + } + } + TopoDS_Shape aShape = theNewShape->impl(); - builder(theTag)->Generated(aShape); - if(!theName.empty()) - buildName(theTag, theName); + builder(myFreePrimitiveTag)->Generated(aShape); + if (!theName.empty()) { + std::string aName = theName; + if (myPrimitivesNamesIndexMap.find(theName) != myPrimitivesNamesIndexMap.end()) { + IndexTags& anIndexTags = myPrimitivesNamesIndexMap.find(theName)->second; + aName += "_" + std::to_string(++(anIndexTags.index)); + anIndexTags.tags.push_back(myFreePrimitiveTag); + if (anIndexTags.index == 2) { + buildName(anIndexTags.tags.front(), theName + "_1"); + } + } + else { + IndexTags anIndexTags; + anIndexTags.index = 1; + anIndexTags.tags.push_back(myFreePrimitiveTag); + myPrimitivesNamesIndexMap[theName] = anIndexTags; + } + + buildName(myFreePrimitiveTag, aName); + } + ++myFreePrimitiveTag; + return true; } -void Model_BodyBuilder::generated(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) +void Model_BodyBuilder::generated(const GeomShapePtr& theOldShape, + const GeomShapePtr& theNewShape, + const std::string& theName) { TopoDS_Shape anOldShape = theOldShape->impl(); TopoDS_Shape aNewShape = theNewShape->impl(); - builder(theTag)->Generated(anOldShape, aNewShape); - if(!theName.empty()) - buildName(theTag, theName); - TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); - if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { - TopAbs_ShapeEnum anExplodeShapeType = aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; - const TDF_Label aLabel = builder(theTag)->NamedShape()->Label(); - int aTag = 1; - std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) { - TDF_Label aChildLabel = aLabel.FindChild(aTag); - TNaming_Builder aBuilder(aChildLabel); - aBuilder.Generated(anOldShape, anExp.Current()); - TCollection_AsciiString aChildName = TCollection_AsciiString((theName + "_").c_str()) + aTag; - //aDoc->addNamingName(aChildLabel, aChildName.ToCString()); - TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); - aTag++; + TopAbs_ShapeEnum aNewShapeType = aNewShape.ShapeType(); + int aTag; + if (aNewShapeType == TopAbs_WIRE || aNewShapeType == TopAbs_SHELL) { + // TODO: This is a workaround. New shape should be only vertex, edge or face. + TopAbs_ShapeEnum aShapeTypeToExplore = aNewShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; + aTag = TopAbs_WIRE ? GENERATED_EDGES_TAG : GENERATED_FACES_TAG; + for (TopExp_Explorer anExp(aNewShape, aShapeTypeToExplore); anExp.More(); anExp.Next()) { + builder(aTag)->Generated(anOldShape, anExp.Current()); } + buildName(aTag, theName); + } else { + aTag = getGenerationTag(aNewShape); + if (aTag == INVALID_TAG) return; + builder(aTag)->Generated(anOldShape, aNewShape); + buildName(aTag, theName); } } - -void Model_BodyBuilder::modified(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) +void Model_BodyBuilder::modified(const GeomShapePtr& theOldShape, + const GeomShapePtr& theNewShape, + const std::string& theName) { TopoDS_Shape anOldShape = theOldShape->impl(); TopoDS_Shape aNewShape = theNewShape->impl(); - builder(theTag)->Modify(anOldShape, aNewShape); - if(!theName.empty()) - buildName(theTag, theName); + int aTag = getModificationTag(aNewShape); + if (aTag == INVALID_TAG) return; + builder(aTag)->Modify(anOldShape, aNewShape); + buildName(aTag, theName); } -void Model_BodyBuilder::deleted(const std::shared_ptr& theOldShape, - const int theTag) +void Model_BodyBuilder::loadDeletedShapes(const GeomMakeShapePtr& theAlgo, + const GeomShapePtr& theOldShape, + const GeomAPI_Shape::ShapeType theShapeTypeToExplore, + const GeomShapePtr& theShapesToExclude) { - TopoDS_Shape aShape = theOldShape->impl(); - builder(theTag)->Delete(aShape); + TopTools_MapOfShape anAlreadyProcessedShapes; + GeomShapePtr aResultShape = shape(); + for (GeomAPI_ShapeExplorer anExp(theOldShape, theShapeTypeToExplore); + anExp.more(); + anExp.next()) + { + GeomShapePtr anOldSubShape = anExp.current(); + const TopoDS_Shape& anOldSubShape_ = anOldSubShape->impl(); + if (!anAlreadyProcessedShapes.Add(anOldSubShape_) + || !theAlgo->isDeleted(anOldSubShape) + || aResultShape->isSubShape(anOldSubShape, false) + || (theShapesToExclude.get() && theShapesToExclude->isSubShape(anOldSubShape, false))) + { + continue; + } + + ListOfShape aNewShapes; + if (BRepTools_History::IsSupportedType(anOldSubShape_)) { // to avoid crash in #2572 + theAlgo->modified(anOldSubShape, aNewShapes); + } + + if (aNewShapes.size() == 0 + || (aNewShapes.size() == 1 && aNewShapes.front()->isSame(anOldSubShape))) { + builder(DELETED_TAG)->Delete(anOldSubShape_); + } + } } -void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag) +// Keep only the shapes with minimal shape type +static void keepTopLevelShapes(ListOfShape& theShapes, + const TopoDS_Shape& theRoot, + const GeomShapePtr& theResultShape = GeomShapePtr()) { - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; ShapeExplorer.More(); ShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = ShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - if (theMS->isDeleted (aRShape)) { - builder(theTag)->Delete(aRoot); + GeomAPI_Shape::ShapeType aKeepShapeType = GeomAPI_Shape::SHAPE; + ListOfShape::iterator anIt = theShapes.begin(); + while (anIt != theShapes.end()) { + TopoDS_Shape aNewShape = (*anIt)->impl(); + bool aSkip = aNewShape.IsNull() || + (aNewShape.ShapeType() == TopAbs_EDGE && BRep_Tool::Degenerated(TopoDS::Edge(aNewShape))); + if (aSkip || theRoot.IsSame(aNewShape) || (theResultShape && + (!theResultShape->isSubShape(*anIt, false) || theResultShape->isSame(*anIt)))) { + ListOfShape::iterator aRemoveIt = anIt++; + theShapes.erase(aRemoveIt); + } else { + GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType(); + if (aType < aKeepShapeType) { + // found a shape with lesser shape type => remove all previous shapes + aKeepShapeType = aType; + theShapes.erase(theShapes.begin(), anIt); + ++anIt; + } else if (aType > aKeepShapeType) { + // shapes with greater shape type should be removed from the list + ListOfShape::iterator aRemoveIt = anIt++; + theShapes.erase(aRemoveIt); + } else + ++anIt; } } } -void Model_BodyBuilder::loadAndOrientModifiedShapes ( - GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag, - const std::string& theName, - GeomAPI_DataMapOfShapeShape& theSubShapes, - const bool theIsStoreSeparate, - const bool theIsStoreAsGenerated) +void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo, + const GeomShapePtr& theOldShape, + const GeomAPI_Shape::ShapeType theShapeTypeToExplore, + const std::string& theName) { - int anIndex = 1; - int aTag = theTag; - bool isBuilt = !theName.empty(); - std::string aName = theName; - std::ostringstream aStream; GeomShapePtr aResultShape = shape(); - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = aShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull()) - continue; // there is no sence to write history is old shape does not persented in document - ListOfShape aList; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - theMS->modified(aRShape, aList); - std::list >::const_iterator - anIt = aList.begin(), aLast = aList.end(); - for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); - if (theSubShapes.isBound(*anIt)) { - std::shared_ptr aMapShape(theSubShapes.find(*anIt)); - aNewShape.Orientation(aMapShape->impl().Orientation()); - } - GeomShapePtr aGeomNewShape(new GeomAPI_Shape()); - aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape)); - if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape)) { - if(theIsStoreAsGenerated) { - // Here we store shapes as generated, to avoid problem when one parent shape produce - // several child shapes. In this case naming could not determine which shape to select. - builder(aTag)->Generated(aRoot,aNewShape); - } else { - builder(aTag)->Modify(aRoot,aNewShape); - } - if(isBuilt) { - if(theIsStoreSeparate) { - aStream.str(std::string()); - aStream.clear(); - aStream << theName << "_" << anIndex++; - aName = aStream.str(); - } - buildName(aTag, aName); - } - if(theIsStoreSeparate) { - aTag++; - } - } + GeomShapePtr aShapeToExplore = theOldShape; + if (theAlgo->isNewShapesCollected(theOldShape, theShapeTypeToExplore)) { + // use optimized set of old shapes for this + GeomShapePtr aCompound = theAlgo->oldShapesForNew(theOldShape, + aResultShape, + theShapeTypeToExplore); + if (aCompound.get()) aShapeToExplore = aCompound; + } + + TopTools_MapOfShape anAlreadyProcessedShapes; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + for (GeomAPI_ShapeExplorer anOldShapeExp(aShapeToExplore, theShapeTypeToExplore); + anOldShapeExp.more(); + anOldShapeExp.next()) + { + GeomShapePtr anOldSubShape = anOldShapeExp.current(); + const TopoDS_Shape& anOldSubShape_ = anOldSubShape->impl(); + + // There is no sense to write history if shape already processed + // or old shape does not exist in the document. + bool anOldSubShapeAlreadyProcessed = !anAlreadyProcessedShapes.Add(anOldSubShape_); + TDF_Label anAccess2 = std::dynamic_pointer_cast( + ModelAPI_Session::get()->moduleDocument())->generalLabel(); + TDF_Label anOriginalLabel; + bool anOldSubShapeNotInTree = + !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel); + if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) { + continue; + } + + // Get new shapes. + ListOfShape aNewShapes; + theAlgo->modified(anOldSubShape, aNewShapes); + + for (ListOfShape::const_iterator aNewShapesIt = aNewShapes.cbegin(); + aNewShapesIt != aNewShapes.cend(); + ++aNewShapesIt) + { + GeomShapePtr aNewShape = *aNewShapesIt; + const TopoDS_Shape& aNewShape_ = aNewShape->impl(); + bool isGenerated = anOldSubShape_.ShapeType() != aNewShape_.ShapeType(); + + bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape); + bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false); + if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape) + continue; + + if (aResultShape->isSame(aNewShape)) + continue; // it is stored on the root level (2241 - history propagation issue) + + 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 + storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label()); } } } -void Model_BodyBuilder::loadAndOrientGeneratedShapes ( - GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag, - const std::string& theName, - GeomAPI_DataMapOfShapeShape& theSubShapes) +void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo, + const GeomShapePtr& theOldShape, + const GeomAPI_Shape::ShapeType theShapeTypeToExplore, + const std::string& theName) { - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - bool isBuilt = !theName.empty(); - TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = aShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull()) - continue; // there is no sence to write history is old shape does not persented in document - ListOfShape aList; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - theMS->generated(aRShape, aList); - std::list >::const_iterator - anIt = aList.begin(), aLast = aList.end(); - for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); - if (theSubShapes.isBound(*anIt)) { - std::shared_ptr aMapShape(theSubShapes.find(*anIt)); - aNewShape.Orientation(aMapShape->impl().Orientation()); - } - if (!aRoot.IsSame (aNewShape)) { - builder(theTag)->Generated(aRoot,aNewShape); - if(isBuilt) - buildName(theTag, theName); + GeomShapePtr aResultShape = shape(); + TopTools_MapOfShape anAlreadyProcessedShapes; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + for (GeomAPI_ShapeExplorer anOldShapeExp(theOldShape, theShapeTypeToExplore); + anOldShapeExp.more(); + anOldShapeExp.next()) + { + GeomShapePtr anOldSubShape = anOldShapeExp.current(); + const TopoDS_Shape& anOldSubShape_ = anOldSubShape->impl(); + + // There is no sense to write history if shape already processed + // or old shape does not exist in the document. + bool anOldSubShapeAlreadyProcessed = !anAlreadyProcessedShapes.Add(anOldSubShape_); + TDF_Label anAccess2 = std::dynamic_pointer_cast( + ModelAPI_Session::get()->moduleDocument())->generalLabel(); + TDF_Label anOriginalLabel; + bool anOldSubShapeNotInTree = + !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel); + if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) { + continue; + } + + // Get new shapes. + ListOfShape aNewShapes; + theAlgo->generated(anOldSubShape, aNewShapes); + + keepTopLevelShapes(aNewShapes, anOldSubShape_); + + for (ListOfShape::const_iterator aNewShapesIt = aNewShapes.cbegin(); + aNewShapesIt != aNewShapes.cend(); + ++aNewShapesIt) + { + GeomShapePtr aNewShape = *aNewShapesIt; + const TopoDS_Shape& aNewShape_ = aNewShape->impl(); + + bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape); + bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false); + if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape) { + continue; } - TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); - if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { - TopAbs_ShapeEnum anExplodeShapeType = - aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; - const TDF_Label aLabel = builder(theTag)->NamedShape()->Label(); - int aTag = 1; - std::shared_ptr aDoc = - std::dynamic_pointer_cast(document()); - for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) { - TDF_Label aChildLabel = aLabel.FindChild(aTag); - TNaming_Builder aBuilder(aChildLabel); - aBuilder.Generated(aRoot, anExp.Current()); - TCollection_AsciiString aChildName = - TCollection_AsciiString((theName + "_").c_str()) + aTag; - TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); - aTag++; + + TopAbs_ShapeEnum aNewShapeType = aNewShape_.ShapeType(); + if (aNewShapeType == TopAbs_WIRE || aNewShapeType == TopAbs_SHELL) { + // TODO: This is a workaround. New shape should be only edge or face. + TopAbs_ShapeEnum aShapeTypeToExplore = aNewShapeType == TopAbs_WIRE ? TopAbs_EDGE + : TopAbs_FACE; + int aTag = TopAbs_WIRE ? GENERATED_EDGES_TAG : GENERATED_FACES_TAG; + for (TopExp_Explorer anExp(aNewShape_, aShapeTypeToExplore); anExp.More(); anExp.Next()) { + builder(aTag)->Generated(anOldSubShape_, anExp.Current()); + // store information about the external document reference to restore old shape on open + storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label()); } + buildName(aTag, theName); + } else { + int aTag = getGenerationTag(aNewShape_); + if (aTag == INVALID_TAG) return; + builder(aTag)->Generated(anOldSubShape_, aNewShape_); + buildName(aTag, theName); + // store information about the external document reference to restore old shape on open + storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label()); } } } } +// LCOV_EXCL_START //======================================================================= int getDangleShapes(const TopoDS_Shape& theShapeIn, const TopAbs_ShapeEnum theGeneratedFrom, @@ -512,10 +738,11 @@ void loadGeneratedDangleShapes( for (; itr.More(); itr.Next()) theBuilder->Generated(itr.Key(), itr.Value()); } +// LCOV_EXCL_STOP //======================================================================= -void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, - const std::string& theName, int& theTag) +void Model_BodyBuilder::loadNextLevels(GeomShapePtr theShape, + const std::string& theName) { if(theShape->isNull()) return; TopoDS_Shape aShape = theShape->impl(); @@ -523,11 +750,11 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, if (aShape.ShapeType() == TopAbs_SOLID) { TopExp_Explorer expl(aShape, TopAbs_FACE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } } else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) { @@ -537,11 +764,11 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) { TopExp_Explorer expl(aShape, TopAbs_FACE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } } TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces; @@ -552,21 +779,21 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, if (aLL.Extent() < 2) { if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i)))) continue; - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } else { TopTools_ListIteratorOfListOfShape anIter(aLL); const TopoDS_Face& aFace = TopoDS::Face(anIter.Value()); anIter.Next(); if(aFace.IsEqual(anIter.Value())) { - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } } } @@ -574,40 +801,40 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, TopTools_IndexedMapOfShape Edges; BRepTools::Map3DEdges(aShape, Edges); if (Edges.Extent() == 1) { - builder(theTag++)->Generated(Edges.FindKey(1)); + builder(myFreePrimitiveTag++)->Generated(Edges.FindKey(1)); TopExp_Explorer expl(aShape, TopAbs_VERTEX); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } } else { TopExp_Explorer expl(aShape, TopAbs_EDGE); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } // and load generated vertices. TopTools_DataMapOfShapeShape generated; if (getDangleShapes(aShape, TopAbs_EDGE, generated)) { - TNaming_Builder* pBuilder = builder(theTag++); + TNaming_Builder* pBuilder = builder(myFreePrimitiveTag++); loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); } } } else if (aShape.ShapeType() == TopAbs_EDGE) { TopExp_Explorer expl(aShape, TopAbs_VERTEX); for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(expl.Current()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; } } } @@ -670,8 +897,7 @@ int findAmbiguities(const TopoDS_Shape& theShapeIn, } //======================================================================= -void Model_BodyBuilder::loadFirstLevel( - std::shared_ptr theShape, const std::string& theName, int& theTag) +void Model_BodyBuilder::loadFirstLevel(GeomShapePtr theShape, const std::string& theName) { if(theShape->isNull()) return; TopoDS_Shape aShape = theShape->impl(); @@ -679,161 +905,44 @@ void Model_BodyBuilder::loadFirstLevel( if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) { TopoDS_Iterator itr(aShape); for (; itr.More(); itr.Next()) { - builder(theTag)->Generated(itr.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - if(!theName.empty()) buildName(theTag, aName); - theTag++; + builder(myFreePrimitiveTag)->Generated(itr.Value()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); + ++myFreePrimitiveTag; if (itr.Value().ShapeType() == TopAbs_COMPOUND || itr.Value().ShapeType() == TopAbs_COMPSOLID) { - std::shared_ptr itrShape(new GeomAPI_Shape()); + GeomShapePtr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadFirstLevel(itrShape, theName, theTag); + loadFirstLevel(itrShape, theName); } else { - std::shared_ptr itrShape(new GeomAPI_Shape()); + GeomShapePtr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadNextLevels(itrShape, theName, theTag); + loadNextLevels(itrShape, theName); } } } else { - std::shared_ptr itrShape(new GeomAPI_Shape()); + GeomShapePtr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(aShape)); - loadNextLevels(itrShape, theName, theTag); + loadNextLevels(itrShape, theName); } TopTools_ListOfShape aList; if(findAmbiguities(aShape, aList)) { TopTools_ListIteratorOfListOfShape it(aList); - for (; it.More(); it.Next(),theTag++) { - builder(theTag)->Generated(it.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - } - } -} - -//======================================================================= -void Model_BodyBuilder::loadDisconnectedEdges( - std::shared_ptr theShape, const std::string& theName, int& theTag) -{ - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - TopTools_DataMapOfShapeListOfShape edgeNaborFaces; - TopTools_ListOfShape empty; - TopExp_Explorer explF(aShape, TopAbs_FACE); - for (; explF.More(); explF.Next()) { - const TopoDS_Shape& aFace = explF.Current(); - TopExp_Explorer explV(aFace, TopAbs_EDGE); - for (; explV.More(); explV.Next()) { - const TopoDS_Shape& anEdge = explV.Current(); - if (!edgeNaborFaces.IsBound(anEdge)) edgeNaborFaces.Bind(anEdge, empty); - Standard_Boolean faceIsNew = Standard_True; - TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge)); - for (; itrF.More(); itrF.Next()) { - if (itrF.Value().IsSame(aFace)) { - faceIsNew = Standard_False; - break; - } - } - if (faceIsNew) - edgeNaborFaces.ChangeFind(anEdge).Append(aFace); - } - } - - TopTools_MapOfShape anEdgesToDelete; - TopExp_Explorer anEx(aShape,TopAbs_EDGE); - std::string aName; - for(;anEx.More();anEx.Next()) { - Standard_Boolean aC0 = Standard_False; - TopoDS_Shape anEdge1 = anEx.Current(); - if (edgeNaborFaces.IsBound(anEdge1)) { - const TopTools_ListOfShape& aList1 = edgeNaborFaces.Find(anEdge1); - if (aList1.Extent()<2) continue; - TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces); - for (; itr.More(); itr.Next()) { - TopoDS_Shape anEdge2 = itr.Key(); - if(anEdgesToDelete.Contains(anEdge2)) continue; - if (anEdge1.IsSame(anEdge2)) continue; - const TopTools_ListOfShape& aList2 = itr.Value(); - // compare lists of the neighbour faces of edge1 and edge2 - if (aList1.Extent() == aList2.Extent()) { - Standard_Integer aMatches = 0; - for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next()) - for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next()) - if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++; - if (aMatches == aList1.Extent()) { - aC0=Standard_True; - builder(theTag)->Generated(anEdge2); - anEdgesToDelete.Add(anEdge2); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } - } - TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete); - for(;itDelete.More();itDelete.Next()) - edgeNaborFaces.UnBind(itDelete.Key()); - edgeNaborFaces.UnBind(anEdge1); - } - if (aC0) { - builder(theTag)->Generated(anEdge1); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } -} - -void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr theShape, - const std::string& theName, int& theTag) -{ - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - TopTools_DataMapOfShapeListOfShape vertexNaborEdges; - TopTools_ListOfShape empty; - TopExp_Explorer explF(aShape, TopAbs_EDGE); - for (; explF.More(); explF.Next()) { - const TopoDS_Shape& anEdge = explF.Current(); - TopExp_Explorer explV(anEdge, TopAbs_VERTEX); - for (; explV.More(); explV.Next()) { - const TopoDS_Shape& aVertex = explV.Current(); - if (!vertexNaborEdges.IsBound(aVertex)) vertexNaborEdges.Bind(aVertex, empty); - Standard_Boolean faceIsNew = Standard_True; - TopTools_ListIteratorOfListOfShape itrF(vertexNaborEdges.Find(aVertex)); - for (; itrF.More(); itrF.Next()) { - if (itrF.Value().IsSame(anEdge)) { - faceIsNew = Standard_False; - break; - } - } - if (faceIsNew) { - vertexNaborEdges.ChangeFind(aVertex).Append(anEdge); - } - } - } - std::string aName; - TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborEdges); - for (; itr.More(); itr.Next()) { - const TopTools_ListOfShape& naborEdges = itr.Value(); - if (naborEdges.Extent() < 2) { - builder(theTag)->Generated(itr.Key()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + for (; it.More(); it.Next(), ++myFreePrimitiveTag) { + builder(myFreePrimitiveTag)->Generated(it.Value()); + TCollection_AsciiString aStr(myFreePrimitiveTag - PRIMITIVES_START_TAG + 1); + aName = theName + "_" + aStr.ToCString(); + buildName(myFreePrimitiveTag, aName); } } } -std::shared_ptr Model_BodyBuilder::shape() +GeomShapePtr Model_BodyBuilder::shape() { std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { + if (aData && aData->isValid()) { TDF_Label aShapeLab = aData->shapeLab(); Handle(TDF_Reference) aRef; if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) { @@ -843,36 +952,11 @@ std::shared_ptr Model_BodyBuilder::shape() if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { TopoDS_Shape aShape = aName->Get(); if (!aShape.IsNull()) { - std::shared_ptr aRes(new GeomAPI_Shape); + GeomShapePtr aRes(new GeomAPI_Shape); aRes->setImpl(new TopoDS_Shape(aShape)); return aRes; } } } - return std::shared_ptr(); -} - -bool Model_BodyBuilder::isLatestEqual(const std::shared_ptr& theShape) -{ - if (theShape.get()) { - TopoDS_Shape aShape = theShape->impl(); - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); - Handle(TNaming_NamedShape) aName; - if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { - TopoDS_Shape aLatest = TNaming_Tool::CurrentShape(aName); - if (aLatest.IsNull()) - return false; - if (aLatest.IsEqual(aShape)) - return true; - // check sub-shapes for comp-solids: - for (TopExp_Explorer anExp(aShape, aLatest.ShapeType()); anExp.More(); anExp.Next()) { - if (aLatest.IsEqual(anExp.Current())) - return true; - } - } - } - } - return false; + return GeomShapePtr(); }