Foundation Classes - Performance improvements for TopExp package (#831)

- Replaced raw pointer-based stack (`TopExp_Stack`) with `NCollection_Vector<TopoDS_Iterator>`
- Mark some methods noexcept
- Removed `myTop` field
This commit is contained in:
Pasukhin Dmitry
2025-11-14 18:00:19 +00:00
committed by GitHub
parent 79289339d8
commit e03b266234
4 changed files with 79 additions and 175 deletions

View File

@@ -6,5 +6,4 @@ set(OCCT_TopExp_FILES
TopExp.hxx
TopExp_Explorer.cxx
TopExp_Explorer.hxx
TopExp_Stack.hxx
)

View File

@@ -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 <TopExp_Explorer.hxx>
#include <Standard_NoMoreObject.hxx>
#include <Standard_NoSuchObject.hxx>
#include <TopAbs.hxx>
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();
}

View File

@@ -17,7 +17,8 @@
#ifndef _TopExp_Explorer_HeaderFile
#define _TopExp_Explorer_HeaderFile
#include <TopExp_Stack.hxx>
#include <NCollection_Vector.hxx>
#include <TopAbs.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Shape.hxx>
@@ -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 <S>.
//!
@@ -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<TopoDS_Iterator> myStack;
TopoDS_Shape myShape;
TopAbs_ShapeEnum toFind;
TopAbs_ShapeEnum toAvoid;
Standard_Boolean hasMore;
};
#endif // _TopExp_Explorer_HeaderFile

View File

@@ -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