X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_BodyBuilder.cpp;h=1a8ea5507f9518ca3810ac4bb6ba615e21bbfe6d;hb=f6bd0f4e080b833c0de7ef25822ebee641073445;hp=fe1541286a3fe7c19cdbfb242a8fe12643b026e6;hpb=3f1a42a51c7de1911c75453ff7134593d7d2c6b1;p=modules%2Fshaper.git diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index fe1541286..1a8ea5507 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: Model_ResultBody.cpp -// Created: 08 Jul 2014 -// Author: Mikhail PONIKAROV +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include @@ -17,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +49,7 @@ #include #include #include +#include #include // DEB //#include @@ -68,27 +84,34 @@ static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) { } for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) { - aShapePairs.push_back(std::pair + // 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); + + // 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 + if (anEvolution == TNaming_DELETE) // issue 2274 : don't put too many same null shapes + aBuilder.Select(aPairsIter->first, aPairsIter->first); + else if (anEvolution == TNaming_PRIMITIVE) + aBuilder.Select(aPairsIter->second, aPairsIter->second); + else + 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); + } } } // recursive call for all sub-labels @@ -114,7 +137,7 @@ void Model_BodyBuilder::store(const std::shared_ptr& theShape, if (aData) { TDF_Label& aShapeLab = aData->shapeLab(); // clean builders - clean(); + clean(); // store the new shape as primitive TNaming_Builder aBuilder(aShapeLab); if (!theShape) @@ -134,7 +157,7 @@ void Model_BodyBuilder::store(const std::shared_ptr& theShape, } } - aBuilder.Generated(aShape); + aBuilder.Generated(aShape); // register name aShapeLab.ForgetAttribute(TDF_Reference::GetID()); if(!aBuilder.NamedShape()->IsEmpty()) { @@ -142,7 +165,8 @@ void Model_BodyBuilder::store(const std::shared_ptr& theShape, 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()); + std::shared_ptr aDoc = + std::dynamic_pointer_cast(document()); aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); } } @@ -157,7 +181,7 @@ void Model_BodyBuilder::storeGenerated(const std::shared_ptr& the if (aData) { TDF_Label& aShapeLab = aData->shapeLab(); // clean builders - clean(); + clean(); // store the new shape as primitive TNaming_Builder aBuilder(aShapeLab); if (!theFromShape || !theToShape) @@ -175,7 +199,8 @@ void Model_BodyBuilder::storeGenerated(const std::shared_ptr& the 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()); + std::shared_ptr aDoc = + std::dynamic_pointer_cast(document()); aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); } } @@ -190,7 +215,8 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr& theO if (aData) { TDF_Label& aShapeLab = aData->shapeLab(); // clean builders - clean(); + if (theDecomposeSolidsTag != -2) + clean(); // store the new shape as primitive TNaming_Builder aBuilder(aShapeLab); if (!theOldShape || !theNewShape) @@ -202,37 +228,14 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr& theO if (aShapeNew.IsNull()) return; // null shape inside aBuilder.Modify(aShapeOld, aShapeNew); - if (theDecomposeSolidsTag && aShapeNew.ShapeType() == TopAbs_COMPOUND) { // make sub elements as subs - - // register name if it is possible - TCollection_AsciiString aName; - if(!aBuilder.NamedShape()->IsEmpty()) { - Handle(TDataStd_Name) anAttr; - if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { - aName = TCollection_AsciiString(anAttr->Get()).ToCString(); - } - } - - TopoDS_Iterator aSubIter(aShapeNew); - for(int aTag = theDecomposeSolidsTag; aSubIter.More(); aSubIter.Next()) { - const TopoDS_Shape& aShape = aSubIter.Value(); - Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aShape, aShapeLab); - if(!aNS.IsNull() && !aNS->IsEmpty()) { - // This shape is already in document, don't add it. - continue; - } - TNaming_Builder aSubBuilder(aShapeLab.FindChild(aTag++)); - aSubBuilder.Generated(aSubIter.Value()); - if(!aName.IsEmpty()) { - TCollection_AsciiString aShapeType = aShape.ShapeType() == TopAbs_EDGE ? "_Edge_" : - aShape.ShapeType() == TopAbs_FACE ? "_Face_" : - aShape.ShapeType() == TopAbs_SOLID ? "_Solid_" : "_Shape_"; - std::string aSolidName = - (aName + aShapeType + TCollection_AsciiString(aTag - theDecomposeSolidsTag)).ToCString(); - std::shared_ptr aDoc = + if(!aBuilder.NamedShape()->IsEmpty()) { + Handle(TDataStd_Name) 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(aSubBuilder.NamedShape()->Label(), aSolidName); - TDataStd_Name::Set(aSubBuilder.NamedShape()->Label(), aSolidName.c_str()); + aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); } } } @@ -243,7 +246,7 @@ void Model_BodyBuilder::storeWithoutNaming(const std::shared_ptr { std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { - clean(); + clean(); if (!theShape.get()) return; // bad shape TopoDS_Shape aShape = theShape->impl(); @@ -256,10 +259,21 @@ void Model_BodyBuilder::storeWithoutNaming(const std::shared_ptr void Model_BodyBuilder::clean() { - std::vector::iterator aBuilder = myBuilders.begin(); - for(; aBuilder != myBuilders.end(); aBuilder++) - delete *aBuilder; + TDF_Label aLab = std::dynamic_pointer_cast(data())->shapeLab(); + if (aLab.IsNull()) + return; + std::map::iterator aBuilder = myBuilders.begin(); + for(; aBuilder != myBuilders.end(); aBuilder++) { + 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(); + } + } myBuilders.clear(); + // remove the old reference (if any) + aLab.ForgetAttribute(TDF_Reference::GetID()); } Model_BodyBuilder::~Model_BodyBuilder() @@ -269,32 +283,28 @@ Model_BodyBuilder::~Model_BodyBuilder() TNaming_Builder* Model_BodyBuilder::builder(const int theTag) { - if (myBuilders.size() <= (unsigned int)theTag) { - myBuilders.insert(myBuilders.end(), theTag - myBuilders.size() + 1, NULL); - } - if (!myBuilders[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(aData->shapeLab().FindChild(theTag)); - //TCollection_AsciiString entry;// - //TDF_Tool::Entry(aData->shapeLab().FindChild(theTag), entry); - //cout << "Label = " <shapeLab() : aData->shapeLab().FindChild(theTag)); + aFind = myBuilders.find(theTag); } - return myBuilders[theTag]; + return aFind->second; } void Model_BodyBuilder::buildName(const int theTag, const std::string& theName) { - std::string aName = data()->name() + "/" + theName; std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(builder(theTag)->NamedShape()->Label(), aName); - TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(),aName.c_str()); + //aDoc->addNamingName(builder(theTag)->NamedShape()->Label(), theName); + TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(), theName.c_str()); } void Model_BodyBuilder::generated( const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) { TopoDS_Shape aShape = theNewShape->impl(); builder(theTag)->Generated(aShape); - if(!theName.empty()) + if(!theName.empty()) buildName(theTag, theName); } @@ -304,7 +314,7 @@ void Model_BodyBuilder::generated(const std::shared_ptr& theOldSh TopoDS_Shape anOldShape = theOldShape->impl(); TopoDS_Shape aNewShape = theNewShape->impl(); builder(theTag)->Generated(anOldShape, aNewShape); - if(!theName.empty()) + if(!theName.empty()) buildName(theTag, theName); TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { @@ -316,8 +326,8 @@ void Model_BodyBuilder::generated(const std::shared_ptr& theOldSh TDF_Label aChildLabel = aLabel.FindChild(aTag); TNaming_Builder aBuilder(aChildLabel); aBuilder.Generated(anOldShape, anExp.Current()); - TCollection_AsciiString aChildName = TCollection_AsciiString((data()->name() + "/" + theName + "_").c_str()) + aTag; - aDoc->addNamingName(aChildLabel, aChildName.ToCString()); + TCollection_AsciiString aChildName = TCollection_AsciiString((theName + "_").c_str()) + aTag; + //aDoc->addNamingName(aChildLabel, aChildName.ToCString()); TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); aTag++; } @@ -331,7 +341,7 @@ void Model_BodyBuilder::modified(const std::shared_ptr& theOldSha TopoDS_Shape anOldShape = theOldShape->impl(); TopoDS_Shape aNewShape = theNewShape->impl(); builder(theTag)->Modify(anOldShape, aNewShape); - if(!theName.empty()) + if(!theName.empty()) buildName(theTag, theName); } @@ -350,17 +360,63 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, TopoDS_Shape aShapeIn = theShapeIn->impl(); TopTools_MapOfShape aView; TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); + GeomShapePtr aResultShape = shape(); 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); + if (!aResultShape->isSubShape(aRShape, false)) { + ListOfShape aHist; + theMS->modified(aRShape, aHist); + if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape))) + builder(theTag)->Delete(aRoot); + } + } + } +} + +// Keep only the shapes with minimal shape type +static void keepTopLevelShapes(ListOfShape& theShapes, const TopoDS_Shape& theRoot, + const GeomShapePtr& theResultShape = GeomShapePtr()) +{ + 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; } } } +// returns an ancestor shape-type thaty used for naming-definition of the sub-type +TopAbs_ShapeEnum typeOfAncestor(const TopAbs_ShapeEnum theSubType) { + if (theSubType == TopAbs_VERTEX) + return TopAbs_EDGE; + if (theSubType == TopAbs_EDGE) + return TopAbs_FACE; + return TopAbs_VERTEX; // bad case +} + void Model_BodyBuilder::loadAndOrientModifiedShapes ( GeomAlgoAPI_MakeShape* theMS, std::shared_ptr theShapeIn, @@ -368,7 +424,8 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( const int theTag, const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes, - const bool theIsStoreSeparate) + const bool theIsStoreSeparate, + const bool theIsStoreAsGenerated) { int anIndex = 1; int aTag = theTag; @@ -378,35 +435,130 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( GeomShapePtr aResultShape = shape(); TopoDS_Shape aShapeIn = theShapeIn->impl(); TopTools_MapOfShape aView; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { const TopoDS_Shape& aRoot = aShapeExplorer.Current (); if (!aView.Add(aRoot)) continue; + + bool aNotInTree = + TNaming_Tool::NamedShape(aRoot, aData->shapeLab()).IsNull(); + if (aNotInTree && !theIsStoreSeparate) { + // there is no sense to write history if old shape does not exist in the document + continue; // but if it is stored separately, it will be builded as a primitive + } 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(); + if (!theIsStoreSeparate) + keepTopLevelShapes(aList, aRoot, aResultShape); + // sort the list of images before naming + GeomAlgoAPI_SortListOfShapes::sort(aList); + + // to trace situation where several objects are produced by one parent (#2317) + int aSameParentShapes = -1; + 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) && aResultShape->isSubShape(*anIt)) { - builder(aTag)->Modify(aRoot,aNewShape); + GeomShapePtr aGeomNewShape(new GeomAPI_Shape()); + aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape)); + if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape, false) && + !aResultShape->isSame(*anIt)) { // to avoid put of same shape on main label and sub + int aBuilderTag = aTag; + if (!theIsStoreSeparate) { + aSameParentShapes++; + } else if (aNotInTree) { // check this new shape can not be represented as + // a sub-shape of higher level sub-shapes + TopAbs_ShapeEnum aNewType = aNewShape.ShapeType(); + TopAbs_ShapeEnum anAncestorType = typeOfAncestor(aNewType); + if (anAncestorType != TopAbs_VERTEX) { + bool aFound = false; + TopoDS_Shape aResultTShape = aResultShape->impl(); + TopExp_Explorer anAncestorExp(aResultTShape, anAncestorType); + for(; anAncestorExp.More() && !aFound; anAncestorExp.Next()) { + if (aResultTShape.IsSame(anAncestorExp.Current())) + continue; + TopExp_Explorer aSubExp(anAncestorExp.Current(), aNewType); + for(; aSubExp.More(); aSubExp.Next()) { + if (aNewShape.IsSame(aSubExp.Current())) { + aFound = true; + break; + } + } + } + if (aFound) { + continue; // not need to store this shape in the BRep structure + } + } + } + + static const int THE_ANCHOR_TAG = 100000; + int aCurShapeType = (int)((*anIt)->shapeType()); + bool needSuffix = false; // suffix for the name based on the shape type + if (aSameParentShapes > 0) { // store in other label + aBuilderTag = THE_ANCHOR_TAG - aSameParentShapes * 10 - aCurShapeType; + needSuffix = true; + } else if (aCurShapeType != theKindOfShape) { + // modified shape has different type => set another tag + // to avoid shapes of different types on the same label + aBuilderTag = THE_ANCHOR_TAG - aCurShapeType; + needSuffix = true; + } + std::string aSuffix; + if (needSuffix) { + switch (aCurShapeType) { + case GeomAPI_Shape::VERTEX: aSuffix = "_v"; break; + case GeomAPI_Shape::EDGE: aSuffix = "_e"; break; + case GeomAPI_Shape::FACE: aSuffix = "_f"; break; + default: break; + } + } + + 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(aBuilderTag)->Generated(aRoot, aNewShape); + } else if (aNotInTree) { + // not in tree -> store as primitive (stored as separated) + builder(aBuilderTag)->Generated(aNewShape); + } else if (aNewShape.ShapeType() > aRoot.ShapeType()) { + // if lower-level type is produced, make it as generated + builder(aBuilderTag)->Generated(aRoot, aNewShape); + } else { + builder(aBuilderTag)->Modify(aRoot, aNewShape); + } if(isBuilt) { - if(theIsStoreSeparate) { + aStream.str(std::string()); + aStream.clear(); + aStream << theName; + if(theIsStoreSeparate) + aStream << "_" << anIndex++; + + if (aSameParentShapes > 0) { aStream.str(std::string()); aStream.clear(); - aStream << theName << "_" << anIndex++; - aName = aStream.str(); + aStream << aName << "_" << aSameParentShapes << "divided"; } - buildName(aTag, aName); + + aStream << aSuffix; + buildName(aBuilderTag, aStream.str()); } if(theIsStoreSeparate) { aTag++; } + } else if (aResultShape->isSame(*anIt)) { + // keep the modification evolution on the root level (2241 - history propagation issue) + if(theIsStoreAsGenerated) { + builder(0)->Generated(aRoot, aNewShape); + } else { + builder(0)->Modify(aRoot, aNewShape); + } } } } @@ -427,11 +579,15 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( 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 sense to write history if old shape does not exist in the 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(); + keepTopLevelShapes(aList, aRoot); + std::list >::const_iterator + anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) { TopoDS_Shape aNewShape = (*anIt)->impl(); if (theSubShapes.isBound(*anIt)) { @@ -445,16 +601,18 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( } TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { - TopAbs_ShapeEnum anExplodeShapeType = aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; + 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()); + 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((data()->name() + "/" + theName + "_").c_str()) + aTag; - aDoc->addNamingName(aChildLabel, aChildName.ToCString()); + TCollection_AsciiString aChildName = + TCollection_AsciiString((theName + "_").c_str()) + aTag; TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); aTag++; } @@ -464,9 +622,9 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( } //======================================================================= -int getDangleShapes(const TopoDS_Shape& theShapeIn, +int getDangleShapes(const TopoDS_Shape& theShapeIn, const TopAbs_ShapeEnum theGeneratedFrom, - TopTools_DataMapOfShapeShape& theDangles) + TopTools_DataMapOfShapeShape& theDangles) { theDangles.Clear(); TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; @@ -492,21 +650,21 @@ void loadGeneratedDangleShapes( TopTools_DataMapOfShapeShape dangles; if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return; TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles); - for (; itr.More(); itr.Next()) + for (; itr.More(); itr.Next()) theBuilder->Generated(itr.Key(), itr.Value()); } //======================================================================= -void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, +void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, const std::string& theName, int& theTag) { if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); + TopoDS_Shape aShape = theShape->impl(); std::string aName; - if (aShape.ShapeType() == TopAbs_SOLID) { + if (aShape.ShapeType() == TopAbs_SOLID) { TopExp_Explorer expl(aShape, TopAbs_FACE); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); + for (; expl.More(); expl.Next()) { + builder(theTag)->Generated(expl.Current()); TCollection_AsciiString aStr(theTag); aName = theName + aStr.ToCString(); buildName(theTag, aName); @@ -520,7 +678,7 @@ 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()); + builder(theTag)->Generated(expl.Current()); TCollection_AsciiString aStr(theTag); aName = theName + aStr.ToCString(); buildName(theTag, aName); @@ -529,7 +687,7 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, } TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces; TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces); - for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) + for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) { const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i); if (aLL.Extent() < 2) { @@ -557,7 +715,7 @@ 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(theTag++)->Generated(Edges.FindKey(1)); TopExp_Explorer expl(aShape, TopAbs_VERTEX); for (; expl.More(); expl.Next()) { builder(theTag)->Generated(expl.Current()); @@ -567,25 +725,25 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, theTag++; } } else { - TopExp_Explorer expl(aShape, TopAbs_EDGE); - for (; expl.More(); expl.Next()) { + 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++; - } + } // and load generated vertices. TopTools_DataMapOfShapeShape generated; - if (getDangleShapes(aShape, TopAbs_EDGE, generated)) + if (getDangleShapes(aShape, TopAbs_EDGE, generated)) { TNaming_Builder* pBuilder = builder(theTag++); - loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); + loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); } } } else if (aShape.ShapeType() == TopAbs_EDGE) { TopExp_Explorer expl(aShape, TopAbs_VERTEX); - for (; expl.More(); expl.Next()) { + for (; expl.More(); expl.Next()) { builder(theTag)->Generated(expl.Current()); TCollection_AsciiString aStr(theTag); aName = theName + aStr.ToCString(); @@ -596,45 +754,60 @@ void Model_BodyBuilder::loadNextLevels(std::shared_ptr theShape, } //======================================================================= -int findAmbiguities(const TopoDS_Shape& theShapeIn, - TopTools_ListOfShape& theList) +int findAmbiguities(const TopoDS_Shape& theShapeIn, + TopTools_ListOfShape& theList) { - int aNumEdges(0); theList.Clear(); - TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; - TopAbs_ShapeEnum aTS(TopAbs_EDGE); - TopAbs_ShapeEnum aTA(TopAbs_FACE); - TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges - TopTools_ListOfShape aKeyList; - TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors); - for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) { - const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i); - const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i); - aMap1.Clear(); - TopTools_ListIteratorOfListOfShape it(ancestors1); - for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1 - for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) { - if (i == j) continue; - const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j); - const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j); - if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) { - int aNum (ancestors2.Extent()); - TopTools_ListIteratorOfListOfShape it(ancestors2); - for(;it.More();it.Next()) - if(aMap1.Contains(it.Value())) aNum--; - if(aNum == 0) { - if(aMap2.Add(aKeyEdge1)) - aKeyList.Append(aKeyEdge1); - if(aMap2.Add(aKeyEdge2)) - aKeyList.Append(aKeyEdge2); + // edges -> ancestor faces list + TopTools_IndexedDataMapOfShapeListOfShape aSubShapeAndAncestors; + TopExp::MapShapesAndAncestors(theShapeIn, TopAbs_EDGE, TopAbs_FACE, aSubShapeAndAncestors); + // keeps the shapes which are already in the resulting list + TopTools_MapOfShape alreadyThere; + // map from faces identifier (combination of hash-codes) to list of edges produced such ID + NCollection_DataMap > aFacesIDs; + + TopTools_IndexedDataMapOfShapeListOfShape::Iterator anAncestorsIter(aSubShapeAndAncestors); + for (; anAncestorsIter.More(); anAncestorsIter.Next()) { + const TopTools_ListOfShape& ancestors = anAncestorsIter.Value(); + if (ancestors.Extent() < 2) + continue; + Standard_Integer anID = 0; + for(TopTools_ListIteratorOfListOfShape aFaceIt(ancestors); aFaceIt.More(); aFaceIt.Next()) { + anID ^= HashCode(aFaceIt.ChangeValue(), 1990657); // Pierpont prime + } + if (aFacesIDs.IsBound(anID)) { // there found same edge, check they really have same faces + const NCollection_List& aSameFaces1 = + aSubShapeAndAncestors.FindFromKey(anAncestorsIter.Key()); + NCollection_List::Iterator aSameEdge(aFacesIDs.ChangeFind(anID)); + for(; aSameEdge.More(); aSameEdge.Next()) { + const NCollection_List& aSameFaces2 = + aSubShapeAndAncestors.FindFromKey(aSameEdge.Value()); + if (aSameFaces2.Extent() != aSameFaces1.Extent()) // the number of faces is different + break; + + NCollection_List::Iterator aFaceIter1(aSameFaces1); + for(; aFaceIter1.More(); aFaceIter1.Next()) { + NCollection_List::Iterator aFaceIter2(aSameFaces2); + for(; aFaceIter2.More(); aFaceIter2.Next()) { + if (aFaceIter1.Value().IsSame(aFaceIter2.Value())) + break; + } + if (!aFaceIter2.More()) // aFaceIter1 contains a face, which is not in aFaceIter2 + break; + } + if (!aFaceIter1.More()) { // all the faces are same => put to the result + if (alreadyThere.Add(aSameEdge.Value())) + theList.Append(aSameEdge.Value()); + if (alreadyThere.Add(anAncestorsIter.Key())) + theList.Append(anAncestorsIter.Key()); } } - } // at the end ==> List of edges to be named in addition + } else { // ID is unique, just add this edge + aFacesIDs.Bind(anID, NCollection_List()); + } + aFacesIDs.ChangeFind(anID).Append(anAncestorsIter.Key()); // add to the list anyway } - aNumEdges = aKeyList.Extent(); - if(aNumEdges) - theList.Assign(aKeyList); - return aNumEdges; + return theList.Extent(); } //======================================================================= @@ -642,32 +815,33 @@ void Model_BodyBuilder::loadFirstLevel( std::shared_ptr theShape, const std::string& theName, int& theTag) { if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); + TopoDS_Shape aShape = theShape->impl(); std::string aName; if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) { TopoDS_Iterator itr(aShape); - for (; itr.More(); itr.Next(),theTag++) { + 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); - if (itr.Value().ShapeType() == TopAbs_COMPOUND || - itr.Value().ShapeType() == TopAbs_COMPSOLID) + theTag++; + if (itr.Value().ShapeType() == TopAbs_COMPOUND || + itr.Value().ShapeType() == TopAbs_COMPSOLID) { std::shared_ptr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(itr.Value())); loadFirstLevel(itrShape, theName, theTag); } else { std::shared_ptr itrShape(new GeomAPI_Shape()); - itrShape->setImpl(new TopoDS_Shape(itr.Value())); + itrShape->setImpl(new TopoDS_Shape(itr.Value())); loadNextLevels(itrShape, theName, theTag); } } } else { std::shared_ptr itrShape(new GeomAPI_Shape()); itrShape->setImpl(new TopoDS_Shape(aShape)); - loadNextLevels(itrShape, theName, theTag); + loadNextLevels(itrShape, theName, theTag); } TopTools_ListOfShape aList; if(findAmbiguities(aShape, aList)) { @@ -686,7 +860,7 @@ void Model_BodyBuilder::loadDisconnectedEdges( std::shared_ptr theShape, const std::string& theName, int& theTag) { if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); + TopoDS_Shape aShape = theShape->impl(); TopTools_DataMapOfShapeListOfShape edgeNaborFaces; TopTools_ListOfShape empty; TopExp_Explorer explF(aShape, TopAbs_FACE); @@ -704,30 +878,13 @@ void Model_BodyBuilder::loadDisconnectedEdges( break; } } - if (faceIsNew) - edgeNaborFaces.ChangeFind(anEdge).Append(aFace); + if (faceIsNew) + edgeNaborFaces.ChangeFind(anEdge).Append(aFace); } } - /* TopTools_IndexedDataMapOfShapeListOfShape aDM; - TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM); - for(int i=1; i <= aDM.Extent(); i++) { - if(aDM.FindFromIndex(i).Extent() > 1) continue; - if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i)))) - continue; - builder(theTag)->Generated(aDM.FindKey(i)); - TCollection_AsciiString aStr(theTag); - std::string aName = theName + aStr.ToCString(); - buildName(theTag, aName); - #ifdef DEB_IMPORT - aName += + ".brep"; - BRepTools::Write(aDM.FindKey(i), aName.c_str()); - #endif - theTag++; - } - */ TopTools_MapOfShape anEdgesToDelete; - TopExp_Explorer anEx(aShape,TopAbs_EDGE); + TopExp_Explorer anEx(aShape,TopAbs_EDGE); std::string aName; for(;anEx.More();anEx.Next()) { Standard_Boolean aC0 = Standard_False; @@ -757,26 +914,27 @@ void Model_BodyBuilder::loadDisconnectedEdges( theTag++; } } - } + } TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete); - for(;itDelete.More();itDelete.Next()) - edgeNaborFaces.UnBind(itDelete.Key()); + 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); + buildName(theTag, aName); theTag++; } - } + } } -void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr theShape, const std::string& theName, int& theTag) +void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr theShape, + const std::string& theName, int& theTag) { if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); + TopoDS_Shape aShape = theShape->impl(); TopTools_DataMapOfShapeListOfShape vertexNaborEdges; TopTools_ListOfShape empty; TopExp_Explorer explF(aShape, TopAbs_EDGE); @@ -803,11 +961,11 @@ void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborEdges); for (; itr.More(); itr.Next()) { const TopTools_ListOfShape& naborEdges = itr.Value(); - if (naborEdges.Extent() < 2) { + if (naborEdges.Extent() < 2) { builder(theTag)->Generated(itr.Key()); TCollection_AsciiString aStr(theTag); aName = theName + aStr.ToCString(); - buildName(theTag, aName); + buildName(theTag, aName); theTag++; } } @@ -838,7 +996,7 @@ std::shared_ptr Model_BodyBuilder::shape() bool Model_BodyBuilder::isLatestEqual(const std::shared_ptr& theShape) { if (theShape.get()) { - TopoDS_Shape aShape = theShape->impl(); + TopoDS_Shape aShape = theShape->impl(); std::shared_ptr aData = std::dynamic_pointer_cast(data()); if (aData) { TDF_Label& aShapeLab = aData->shapeLab();