X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_BodyBuilder.cpp;h=1a8ea5507f9518ca3810ac4bb6ba615e21bbfe6d;hb=f6bd0f4e080b833c0de7ef25822ebee641073445;hp=2adab6e8ff9ee133bb22f613d2571599b681e3b6;hpb=10188f6e049f86beb78e076a88d28c298c9812da;p=modules%2Fshaper.git diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 2adab6e8f..1a8ea5507 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include // DEB //#include @@ -214,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) @@ -358,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, @@ -387,16 +435,27 @@ 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; - 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 + + 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); + 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 @@ -412,34 +471,83 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( 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) + 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 = 100000 - aSameParentShapes * 10 - aTag; + 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 << "_" << anIndex++; - aName = aStream.str(); - } + aStream.str(std::string()); + aStream.clear(); + aStream << theName; + if(theIsStoreSeparate) + aStream << "_" << anIndex++; + if (aSameParentShapes > 0) { aStream.str(std::string()); aStream.clear(); aStream << aName << "_" << aSameParentShapes << "divided"; - std::string aNameDiv = aStream.str(); - buildName(aBuilderTag, aNameDiv); - } else { - buildName(aBuilderTag, aName); } + + aStream << aSuffix; + buildName(aBuilderTag, aStream.str()); } if(theIsStoreSeparate) { aTag++; @@ -477,6 +585,7 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( std::shared_ptr aRShape(new GeomAPI_Shape()); aRShape->setImpl((new TopoDS_Shape(aRoot))); theMS->generated(aRShape, aList); + keepTopLevelShapes(aList, aRoot); std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) {