From 66df8b51b6c25894f9ce61d7d516aa9004ea8dc5 Mon Sep 17 00:00:00 2001 From: Konstantin Leontev Date: Mon, 6 Nov 2023 17:42:32 +0000 Subject: [PATCH] [bos #38090][CEA] improve loadModifiedShapes. Added caching sub-shapes to a map before a loop to avoid exploring subs on each iteration. --- src/Model/Model_BodyBuilder.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index eaea11a1a..4fde343b5 100644 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -634,6 +634,11 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo, 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(), aResultShapeSubMap); + TopTools_MapOfShape anAlreadyProcessedShapes; std::shared_ptr aData = std::dynamic_pointer_cast(data()); for (GeomAPI_ShapeExplorer anOldShapeExp(aShapeToExplore, theShapeTypeToExplore); @@ -645,36 +650,40 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo, // 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(); + if (!anAlreadyProcessedShapes.Add(anOldSubShape_)) + { + continue; + } + + 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) { + 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(); - 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_)) -- 2.30.2