X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_BodyBuilder.cpp;h=1a8ea5507f9518ca3810ac4bb6ba615e21bbfe6d;hb=f6bd0f4e080b833c0de7ef25822ebee641073445;hp=7383893501168275c139f7ca92e9f57e9500ac7e;hpb=ade68d25465a422af49d71881550bd89a2ecb824;p=modules%2Fshaper.git diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 738389350..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) @@ -270,6 +272,8 @@ void Model_BodyBuilder::clean() } } myBuilders.clear(); + // remove the old reference (if any) + aLab.ForgetAttribute(TDF_Reference::GetID()); } Model_BodyBuilder::~Model_BodyBuilder() @@ -282,7 +286,8 @@ 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(aData->shapeLab().FindChild(theTag)); + myBuilders[theTag] = new TNaming_Builder( + theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag)); aFind = myBuilders.find(theTag); } return aFind->second; @@ -355,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, @@ -384,16 +435,29 @@ 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 sence to write history is old shape does not persented in 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 anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) { @@ -404,26 +468,97 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes ( } GeomShapePtr aGeomNewShape(new GeomAPI_Shape()); aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape)); - if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape)) { + 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(aTag)->Generated(aRoot,aNewShape); + 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(aTag)->Modify(aRoot,aNewShape); + 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); + } } } } @@ -444,12 +579,13 @@ 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 sence to write history is old shape does not persented in document + //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); + keepTopLevelShapes(aList, aRoot); std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) {