-// Copyright (C) 2014-2020 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
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;
+ Handle(TNaming_NamedShape) aNS;
if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
if (aNS->Evolution() != TNaming_SELECTED) {
theOriginalLabel = aNS->Label();
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;
+ aTag = aNewShapeType == TopAbs_WIRE ? GENERATED_EDGES_TAG : GENERATED_FACES_TAG;
for (TopExp_Explorer anExp(aNewShape, aShapeTypeToExplore); anExp.More(); anExp.Next()) {
builder(aTag)->Generated(anOldShape, anExp.Current());
}
if (aCompound.get()) aShapeToExplore = aCompound;
}
+ // Store all types of subshapes in the map to use them for checking
+ // if the new shapes are sub-shapes of this result
+ TopTools_MapOfShape aResultShapeSubMap;
+ TopExp::MapShapes(aResultShape->impl<TopoDS_Shape>(), aResultShapeSubMap);
+
TopTools_MapOfShape anAlreadyProcessedShapes;
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
for (GeomAPI_ShapeExplorer anOldShapeExp(aShapeToExplore, theShapeTypeToExplore);
// 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<Model_Document>(
- ModelAPI_Session::get()->moduleDocument())->generalLabel();
+ if (!anAlreadyProcessedShapes.Add(anOldSubShape_))
+ {
+ continue;
+ }
+
+ TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(ModelAPI_Session::get()->moduleDocument())->generalLabel();
TDF_Label anOriginalLabel;
- bool anOldSubShapeNotInTree =
- !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel);
- if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) {
+ if (!isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel))
+ {
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<TopoDS_Shape>();
- bool isGenerated = anOldSubShape_.ShapeType() != aNewShape_.ShapeType();
- bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape);
- bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false);
- if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape)
+ if (anOldSubShape->isSame(aNewShape))
continue;
if (aResultShape->isSame(aNewShape))
continue; // it is stored on the root level (2241 - history propagation issue)
+ // Look in the map instead of aResultShape->isSubShape(aNewShape, false)
+ // to avoid many iterations of sub-shapes hierarchy that leads to performance issues
+ if (!aResultShapeSubMap.Contains(aNewShape_))
+ continue;
+
+ const bool isGenerated = anOldSubShape_.ShapeType() != aNewShape_.ShapeType();
int aTag = isGenerated ? getGenerationTag(aNewShape_) : getModificationTag(aNewShape_);
TNaming_Builder*aBuilder = builder(aTag);
if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_))
bool anOldSubShapeNotInTree =
!isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel);
if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) {
- if (theSaveOldIfNotInTree) {
+ // The second condition is added due to #20170 because sub-shape must be added to real parent
+ // shape, not the reference. The naming name of pure reference is not registered in document.
+ if (theSaveOldIfNotInTree && !aData->shapeLab().IsAttribute(TDF_Reference::GetID())) {
std::string aSelectionName = theName + "Selected";
generated(anOldSubShape, aSelectionName, false);
} else
// 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;
+ int aTag = aNewShapeType == 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