From e03b26623473564aacad6b6672a346fc602d494c Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Fri, 14 Nov 2025 18:00:19 +0000 Subject: [PATCH] Foundation Classes - Performance improvements for TopExp package (#831) - Replaced raw pointer-based stack (`TopExp_Stack`) with `NCollection_Vector` - Mark some methods noexcept - Removed `myTop` field --- src/ModelingData/TKBRep/TopExp/FILES.cmake | 1 - .../TKBRep/TopExp/TopExp_Explorer.cxx | 192 ++++++------------ .../TKBRep/TopExp/TopExp_Explorer.hxx | 38 ++-- .../TKBRep/TopExp/TopExp_Stack.hxx | 23 --- 4 files changed, 79 insertions(+), 175 deletions(-) delete mode 100644 src/ModelingData/TKBRep/TopExp/TopExp_Stack.hxx diff --git a/src/ModelingData/TKBRep/TopExp/FILES.cmake b/src/ModelingData/TKBRep/TopExp/FILES.cmake index e1d85bccdd..0fca5302ce 100644 --- a/src/ModelingData/TKBRep/TopExp/FILES.cmake +++ b/src/ModelingData/TKBRep/TopExp/FILES.cmake @@ -6,5 +6,4 @@ set(OCCT_TopExp_FILES TopExp.hxx TopExp_Explorer.cxx TopExp_Explorer.hxx - TopExp_Stack.hxx ) diff --git a/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.cxx b/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.cxx index 049e0b5f37..48abb9320e 100644 --- a/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.cxx +++ b/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.cxx @@ -1,7 +1,5 @@ -// Created on: 1993-01-18 -// Created by: Remi LEQUETTE // Copyright (c) 1993-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS +// Copyright (c) 1999-2025 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -14,51 +12,60 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#define No_Standard_NoMoreObject -#define No_Standard_NoSuchObject - #include -#include -#include -#include +namespace +{ +//! Returns true if the given type matches the type to find. +inline Standard_Boolean isSameType(const TopAbs_ShapeEnum theType, + const TopAbs_ShapeEnum toFind) noexcept +{ + return toFind == theType; +} -// macro to compare two types of shapes -// always True if the first one is SHAPE -#define SAMETYPE(x, y) ((x) == (y)) -#define AVOID(x, y) (((x) == TopAbs_SHAPE) ? Standard_False : (x) == (y)) -#define LESSCOMPLEX(x, y) ((x) > (y)) +//! Returns true if the given type should be avoided. +inline Standard_Boolean shouldAvoid(const TopAbs_ShapeEnum theType, + const TopAbs_ShapeEnum toAvoid) noexcept +{ + return toAvoid != TopAbs_SHAPE && toAvoid == theType; +} -static const Standard_Integer theStackSize = 20; +//! Returns true if the given type is more complex than the type to find. +inline Standard_Boolean isMoreComplex(const TopAbs_ShapeEnum theType, + const TopAbs_ShapeEnum toFind) noexcept +{ + return toFind > theType; +} +} // namespace //================================================================================================= -TopExp_Explorer::TopExp_Explorer() - : myStack(0L), - myTop(-1), - mySizeOfStack(theStackSize), +TopExp_Explorer::TopExp_Explorer() noexcept + : myStack(20), toFind(TopAbs_SHAPE), toAvoid(TopAbs_SHAPE), hasMore(Standard_False) { - myStack = (TopoDS_Iterator*)Standard::Allocate(theStackSize * sizeof(TopoDS_Iterator)); } //================================================================================================= -TopExp_Explorer::TopExp_Explorer(const TopoDS_Shape& theS, - const TopAbs_ShapeEnum theToFind, - const TopAbs_ShapeEnum theToAvoid) - : myStack(0L), - myTop(-1), - mySizeOfStack(theStackSize), - toFind(theToFind), - toAvoid(theToAvoid), +TopExp_Explorer::TopExp_Explorer(const TopoDS_Shape& S, + const TopAbs_ShapeEnum ToFind, + const TopAbs_ShapeEnum ToAvoid) + : myStack(20), + toFind(ToFind), + toAvoid(ToAvoid), hasMore(Standard_False) { - myStack = (TopoDS_Iterator*)Standard::Allocate(theStackSize * sizeof(TopoDS_Iterator)); + Init(S, ToFind, ToAvoid); +} - Init(theS, theToFind, theToAvoid); +//================================================================================================= + +TopExp_Explorer::~TopExp_Explorer() +{ + Clear(); } //================================================================================================= @@ -79,34 +86,23 @@ void TopExp_Explorer::Init(const TopoDS_Shape& S, return; } -#if 0 - // for SOLID, FACE, EDGE ignores the initial orientation - TopAbs_ShapeEnum T = myShape.ShapeType(); - if ((T == TopAbs_SOLID) || (T == TopAbs_FACE) || (T == TopAbs_EDGE)) - myShape.Orientation(TopAbs_FORWARD); -#endif - if (toFind == TopAbs_SHAPE) hasMore = Standard_False; - else { TopAbs_ShapeEnum ty = S.ShapeType(); - if (LESSCOMPLEX(ty, toFind)) + if (ty > toFind) { - // the first Shape is less complex, nothing to find hasMore = Standard_False; } - else if (!SAMETYPE(ty, toFind)) + else if (!isSameType(ty, toFind)) { - // type is more complex search inside hasMore = Standard_True; Next(); } else { - // type is found hasMore = Standard_True; } } @@ -114,110 +110,60 @@ void TopExp_Explorer::Init(const TopoDS_Shape& S, //================================================================================================= -const TopoDS_Shape& TopExp_Explorer::Current() const -{ - Standard_NoSuchObject_Raise_if(!hasMore, "TopExp_Explorer::Current"); - if (myTop >= 0) - { - const TopoDS_Shape& S = myStack[myTop].Value(); - return S; - } - else - return myShape; -} - -//================================================================================================= - void TopExp_Explorer::Next() { - Standard_Integer NewSize; - TopoDS_Shape ShapTop; - TopAbs_ShapeEnum ty; - Standard_NoMoreObject_Raise_if(!hasMore, "TopExp_Explorer::Next"); - - if (myTop < 0) + if (myStack.IsEmpty()) { - // empty stack. Entering the initial shape. - ty = myShape.ShapeType(); + TopAbs_ShapeEnum ty = myShape.ShapeType(); - if (SAMETYPE(toFind, ty)) + if (isSameType(ty, toFind)) { - // already visited once hasMore = Standard_False; return; } - else if (AVOID(toAvoid, ty)) + else if (shouldAvoid(ty, toAvoid)) { - // avoid the top-level hasMore = Standard_False; return; } else { - // push and try to find - if (++myTop >= mySizeOfStack) - { - NewSize = mySizeOfStack + theStackSize; - TopExp_Stack newStack = - (TopoDS_Iterator*)Standard::Allocate(NewSize * sizeof(TopoDS_Iterator)); - Standard_Integer i; - for (i = 0; i < myTop; i++) - { - new (&newStack[i]) TopoDS_Iterator(myStack[i]); - myStack[i].~TopoDS_Iterator(); - } - Standard::Free(myStack); - mySizeOfStack = NewSize; - myStack = newStack; - } - new (&myStack[myTop]) TopoDS_Iterator(myShape); + myStack.Append(TopoDS_Iterator(myShape)); } } else - myStack[myTop].Next(); + myStack.ChangeLast().Next(); for (;;) { - if (myStack[myTop].More()) + TopoDS_Iterator& aTopIter = myStack.ChangeLast(); + + if (aTopIter.More()) { - ShapTop = myStack[myTop].Value(); - ty = ShapTop.ShapeType(); - if (SAMETYPE(toFind, ty)) + const TopoDS_Shape& aShapTop = aTopIter.Value(); + const TopAbs_ShapeEnum ty = aShapTop.ShapeType(); + + if (isSameType(ty, toFind)) { hasMore = Standard_True; return; } - else if (LESSCOMPLEX(toFind, ty) && !AVOID(toAvoid, ty)) + else if (isMoreComplex(ty, toFind) && !shouldAvoid(ty, toAvoid)) { - if (++myTop >= mySizeOfStack) - { - NewSize = mySizeOfStack + theStackSize; - TopExp_Stack newStack = - (TopoDS_Iterator*)Standard::Allocate(NewSize * sizeof(TopoDS_Iterator)); - Standard_Integer i; - for (i = 0; i < myTop; i++) - { - new (&newStack[i]) TopoDS_Iterator(myStack[i]); - myStack[i].~TopoDS_Iterator(); - } - Standard::Free(myStack); - mySizeOfStack = NewSize; - myStack = newStack; - } - new (&myStack[myTop]) TopoDS_Iterator(ShapTop); + myStack.Append(TopoDS_Iterator(aShapTop)); + // aTopIter reference is now invalid after Append } else { - myStack[myTop].Next(); + aTopIter.Next(); } } else { - myStack[myTop].~TopoDS_Iterator(); - myTop--; - if (myTop < 0) + myStack.EraseLast(); + if (myStack.IsEmpty()) break; - myStack[myTop].Next(); + myStack.ChangeLast().Next(); } } hasMore = Standard_False; @@ -225,22 +171,16 @@ void TopExp_Explorer::Next() //================================================================================================= -void TopExp_Explorer::ReInit() +const TopoDS_Shape& TopExp_Explorer::Current() const noexcept { - Init(myShape, toFind, toAvoid); + return myStack.IsEmpty() ? myShape : myStack.Last().Value(); } //================================================================================================= -TopExp_Explorer::~TopExp_Explorer() +Standard_Integer TopExp_Explorer::Depth() const noexcept { - Clear(); - if (myStack) - { - Standard::Free(myStack); - } - mySizeOfStack = 0; - myStack = 0L; + return myStack.Length(); } //================================================================================================= @@ -248,9 +188,5 @@ TopExp_Explorer::~TopExp_Explorer() void TopExp_Explorer::Clear() { hasMore = Standard_False; - for (int i = 0; i <= myTop; ++i) - { - myStack[i].~TopoDS_Iterator(); - } - myTop = -1; + myStack.Clear(); } diff --git a/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.hxx b/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.hxx index da01d72707..be922acd06 100644 --- a/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.hxx +++ b/src/ModelingData/TKBRep/TopExp/TopExp_Explorer.hxx @@ -17,7 +17,8 @@ #ifndef _TopExp_Explorer_HeaderFile #define _TopExp_Explorer_HeaderFile -#include +#include +#include #include #include @@ -84,7 +85,7 @@ public: DEFINE_STANDARD_ALLOC //! Creates an empty explorer, becomes useful after Init. - Standard_EXPORT TopExp_Explorer(); + Standard_EXPORT TopExp_Explorer() noexcept; //! Creates an Explorer on the Shape . //! @@ -110,48 +111,39 @@ public: const TopAbs_ShapeEnum ToAvoid = TopAbs_SHAPE); //! Returns True if there are more shapes in the exploration. - Standard_Boolean More() const { return hasMore; } + Standard_Boolean More() const noexcept { return hasMore; } //! Moves to the next Shape in the exploration. - //! Exceptions - //! Standard_NoMoreObject if there are no more shapes to explore. Standard_EXPORT void Next(); //! Returns the current shape in the exploration. - //! Exceptions - //! Standard_NoSuchObject if this explorer has no more shapes to explore. - const TopoDS_Shape& Value() const { return Current(); } + const TopoDS_Shape& Value() const noexcept { return Current(); } //! Returns the current shape in the exploration. - //! Exceptions - //! Standard_NoSuchObject if this explorer has no more shapes to explore. - Standard_EXPORT const TopoDS_Shape& Current() const; + Standard_EXPORT const TopoDS_Shape& Current() const noexcept; //! Reinitialize the exploration with the original arguments. - Standard_EXPORT void ReInit(); + void ReInit() { Init(myShape, toFind, toAvoid); } //! Return explored shape. - const TopoDS_Shape& ExploredShape() const { return myShape; } + const TopoDS_Shape& ExploredShape() const noexcept { return myShape; } //! Returns the current depth of the exploration. 0 is //! the shape to explore itself. - Standard_Integer Depth() const { return myTop; } + Standard_EXPORT Standard_Integer Depth() const noexcept; - //! Clears the content of the explorer. It will return - //! False on More(). + //! Clears the content of the explorer. Standard_EXPORT void Clear(); //! Destructor. Standard_EXPORT ~TopExp_Explorer(); private: - TopExp_Stack myStack; - TopoDS_Shape myShape; - Standard_Integer myTop; - Standard_Integer mySizeOfStack; - TopAbs_ShapeEnum toFind; - TopAbs_ShapeEnum toAvoid; - Standard_Boolean hasMore; + NCollection_Vector myStack; + TopoDS_Shape myShape; + TopAbs_ShapeEnum toFind; + TopAbs_ShapeEnum toAvoid; + Standard_Boolean hasMore; }; #endif // _TopExp_Explorer_HeaderFile diff --git a/src/ModelingData/TKBRep/TopExp/TopExp_Stack.hxx b/src/ModelingData/TKBRep/TopExp/TopExp_Stack.hxx deleted file mode 100644 index 1bff81268e..0000000000 --- a/src/ModelingData/TKBRep/TopExp/TopExp_Stack.hxx +++ /dev/null @@ -1,23 +0,0 @@ -// Created on: 1990-12-20 -// Created by: Remi Lequette -// Copyright (c) 1990-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _TopExp_Stack_HeaderFile -#define _TopExp_Stack_HeaderFile - -class TopoDS_Iterator; -typedef TopoDS_Iterator* TopExp_Stack; - -#endif // _TopExp_Stack_HeaderFile -- 2.39.5