Mesh - Replace plugin system with registry-based factory pattern (#1033)

Replace the legacy DISCRETPLUGIN/DISCRETALGO symbol-based plugin system
with a clean registry-based factory pattern following the design of
Graphic3d_GraphicDriverFactory.

Problem: TKMesh and TKXMesh both exported the same DISCRETALGO symbol,
causing symbol collisions when both libraries were loaded. The old plugin
system required dlopen/dlsym which was error-prone and limited.

Solution: Each meshing algorithm now registers itself as a factory with
a unique name. Multiple algorithms can coexist and be selected at runtime.

New classes:
- BRepMesh_DiscretAlgoFactory: Abstract factory base with static registry
- BRepMesh_IncrementalMeshFactory: Factory for "FastDiscret" algorithm
- XBRepMesh_Factory: Factory for "XBRepMesh" algorithm

Removed (breaking changes):
- BRepMesh_PluginMacro.hxx: DISCRETPLUGIN macro
- BRepMesh_PluginEntryType.hxx: Legacy function pointer type
- BRepMesh_FactoryError.hxx: Legacy error enum
- XBRepMesh class: Replaced by XBRepMesh_Factory
- BRepMesh_DiscretFactory::Names(), SetFunctionName(), FunctionName(), ErrorStatus()
- Draw commands: mpsetfunctionname, mpgetfunctionname, mperror

Simplified BRepMesh_DiscretFactory API to delegate to the new registry.
Updated MeshTest_PluginCommands to use BRepMesh_DiscretAlgoFactory.
This commit is contained in:
Pasukhin Dmitry
2026-01-24 16:52:30 +00:00
committed by GitHub
parent 553466c590
commit c47d9c06b5
19 changed files with 634 additions and 480 deletions
@@ -0,0 +1,114 @@
// Copyright (c) 2025 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.
#include <BRepMesh_DiscretAlgoFactory.hxx>
#include <BRepMesh_DiscretRoot.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DiscretAlgoFactory, Standard_Transient)
namespace
{
static NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& getFactories()
{
static NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>> TheFactories;
return TheFactories;
}
} // namespace
//==================================================================================================
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& BRepMesh_DiscretAlgoFactory::
Factories()
{
return getFactories();
}
//==================================================================================================
void BRepMesh_DiscretAlgoFactory::RegisterFactory(
const occ::handle<BRepMesh_DiscretAlgoFactory>& theFactory,
bool theIsPreferred)
{
const TCollection_AsciiString aName = theFactory->Name();
NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories = getFactories();
if (theIsPreferred)
{
UnregisterFactory(aName);
aFactories.Prepend(theFactory);
return;
}
for (NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>::Iterator anIter(aFactories);
anIter.More();
anIter.Next())
{
if (TCollection_AsciiString::IsSameString(anIter.Value()->Name(), aName, false))
{
return;
}
}
aFactories.Append(theFactory);
}
//==================================================================================================
void BRepMesh_DiscretAlgoFactory::UnregisterFactory(const TCollection_AsciiString& theName)
{
NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories = getFactories();
for (NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>::Iterator anIter(aFactories);
anIter.More();)
{
if (TCollection_AsciiString::IsSameString(anIter.Value()->Name(), theName, false))
{
aFactories.Remove(anIter);
}
else
{
anIter.Next();
}
}
}
//==================================================================================================
occ::handle<BRepMesh_DiscretAlgoFactory> BRepMesh_DiscretAlgoFactory::DefaultFactory()
{
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories = getFactories();
return !aFactories.IsEmpty() ? aFactories.First() : occ::handle<BRepMesh_DiscretAlgoFactory>();
}
//==================================================================================================
occ::handle<BRepMesh_DiscretAlgoFactory> BRepMesh_DiscretAlgoFactory::FindFactory(
const TCollection_AsciiString& theName)
{
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories = getFactories();
for (NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>::Iterator anIter(aFactories);
anIter.More();
anIter.Next())
{
if (TCollection_AsciiString::IsSameString(anIter.Value()->Name(), theName, false))
{
return anIter.Value();
}
}
return occ::handle<BRepMesh_DiscretAlgoFactory>();
}
//==================================================================================================
BRepMesh_DiscretAlgoFactory::BRepMesh_DiscretAlgoFactory(const TCollection_AsciiString& theName)
: myName(theName)
{
}
@@ -0,0 +1,81 @@
// Copyright (c) 2025 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 _BRepMesh_DiscretAlgoFactory_HeaderFile
#define _BRepMesh_DiscretAlgoFactory_HeaderFile
#include <NCollection_List.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Type.hxx>
#include <TCollection_AsciiString.hxx>
class BRepMesh_DiscretRoot;
class TopoDS_Shape;
//! Abstract factory for creating meshing algorithms.
//! This class provides a registry-based factory pattern that allows multiple
//! meshing algorithms to coexist without symbol collisions.
//! It follows the pattern established by Graphic3d_GraphicDriverFactory.
class BRepMesh_DiscretAlgoFactory : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(BRepMesh_DiscretAlgoFactory, Standard_Transient)
public:
//! Registers a factory in the global registry.
//! @param[in] theFactory factory to register
//! @param[in] theIsPreferred if TRUE, add to the beginning of the list (making it default),
//! otherwise add to the end
Standard_EXPORT static void RegisterFactory(
const occ::handle<BRepMesh_DiscretAlgoFactory>& theFactory,
bool theIsPreferred = false);
//! Unregisters a factory by name.
//! @param[in] theName name of the factory to unregister
Standard_EXPORT static void UnregisterFactory(const TCollection_AsciiString& theName);
//! Returns the default (first registered) factory, or NULL if none registered.
Standard_EXPORT static occ::handle<BRepMesh_DiscretAlgoFactory> DefaultFactory();
//! Finds a factory by name.
//! @param[in] theName name of the factory to find
//! @return factory handle, or NULL if not found
Standard_EXPORT static occ::handle<BRepMesh_DiscretAlgoFactory> FindFactory(
const TCollection_AsciiString& theName);
//! Returns the global list of registered factories.
Standard_EXPORT static const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>&
Factories();
public:
//! Creates a new meshing algorithm instance.
//! @param[in] theShape shape to be meshed
//! @param[in] theLinDeflection linear deflection for meshing
//! @param[in] theAngDeflection angular deflection for meshing
//! @return new meshing algorithm instance
virtual occ::handle<BRepMesh_DiscretRoot> CreateAlgorithm(const TopoDS_Shape& theShape,
double theLinDeflection,
double theAngDeflection) = 0;
//! Returns the factory name.
const TCollection_AsciiString& Name() const { return myName; }
protected:
//! Constructor.
//! @param[in] theName factory name used for identification
Standard_EXPORT BRepMesh_DiscretAlgoFactory(const TCollection_AsciiString& theName);
protected:
TCollection_AsciiString myName;
};
#endif // _BRepMesh_DiscretAlgoFactory_HeaderFile
@@ -15,173 +15,52 @@
#include <BRepMesh_DiscretFactory.hxx>
#include <OSD_SharedLibrary.hxx>
#include <OSD_Function.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepMesh_DiscretAlgoFactory.hxx>
namespace
{
//! Embedded triangulation tool(s)
static TCollection_AsciiString THE_FAST_DISCRET_MESH("FastDiscret");
//! Generate system-dependent name for dynamic library
//! (add standard prefixes and postfixes)
static void MakeLibName(const TCollection_AsciiString& theDefaultName,
TCollection_AsciiString& theLibName)
{
theLibName = "";
#ifndef _WIN32
theLibName += "lib";
#endif
theLibName += theDefaultName;
#ifdef _WIN32
theLibName += ".dll";
#elif __APPLE__
theLibName += ".dylib";
#elif defined(HPUX) || defined(_hpux)
theLibName += ".sl";
#else
theLibName += ".so";
#endif
}
} // namespace
//=================================================================================================
//==================================================================================================
BRepMesh_DiscretFactory::BRepMesh_DiscretFactory()
: myPluginEntry(nullptr),
myErrorStatus(BRepMesh_FE_NOERROR),
myDefaultName(THE_FAST_DISCRET_MESH),
myFunctionName("DISCRETALGO")
: myDefaultName("FastDiscret")
{
// register built-in meshing algorithms
myNames.Add(THE_FAST_DISCRET_MESH);
}
//=================================================================================================
BRepMesh_DiscretFactory::~BRepMesh_DiscretFactory()
{
clear();
}
//=================================================================================================
void BRepMesh_DiscretFactory::clear()
{
// what should we do here? Unload dynamic libraries and reset plugins list?
}
//=================================================================================================
//==================================================================================================
BRepMesh_DiscretFactory& BRepMesh_DiscretFactory::Get()
{
//! global factory instance
static BRepMesh_DiscretFactory THE_GLOBAL_FACTORY;
return THE_GLOBAL_FACTORY;
}
//=================================================================================================
//==================================================================================================
bool BRepMesh_DiscretFactory::SetDefault(const TCollection_AsciiString& theName,
const TCollection_AsciiString& theFuncName)
bool BRepMesh_DiscretFactory::SetDefaultName(const TCollection_AsciiString& theName)
{
myErrorStatus = BRepMesh_FE_NOERROR;
if (theName == THE_FAST_DISCRET_MESH)
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory =
BRepMesh_DiscretAlgoFactory::FindFactory(theName);
if (aFactory.IsNull())
{
// built-in, nothing to do
myPluginEntry = nullptr;
myDefaultName = theName;
myFunctionName = theFuncName;
return true;
}
else if (theName == myDefaultName && theFuncName == myFunctionName)
{
// already active
return myPluginEntry != nullptr;
}
TCollection_AsciiString aMeshAlgoId = theName + "_" + theFuncName;
BRepMesh_PluginEntryType aFunc = nullptr;
if (myFactoryMethods.IsBound(aMeshAlgoId))
{
// retrieve from cache
aFunc = (BRepMesh_PluginEntryType)myFactoryMethods(aMeshAlgoId);
}
else
{
TCollection_AsciiString aLibName;
MakeLibName(theName, aLibName);
OSD_SharedLibrary aSL(aLibName.ToCString());
if (!aSL.DlOpen(OSD_RTLD_LAZY))
{
// library is not found
myErrorStatus = BRepMesh_FE_LIBRARYNOTFOUND;
return false;
}
// retrieve the function from plugin
aFunc = (BRepMesh_PluginEntryType)aSL.DlSymb(theFuncName.ToCString());
myFactoryMethods.Bind(aMeshAlgoId, (OSD_Function)aFunc);
}
if (aFunc == nullptr)
{
// function is not found - invalid plugin?
myErrorStatus = BRepMesh_FE_FUNCTIONNOTFOUND;
return false;
}
// try to create dummy tool
BRepMesh_DiscretRoot* anInstancePtr = nullptr;
int anErr = aFunc(TopoDS_Shape(), 0.001, 0.1, anInstancePtr);
if (anErr != 0 || anInstancePtr == nullptr)
{
// can not create the algo specified
myErrorStatus = BRepMesh_FE_CANNOTCREATEALGO;
delete anInstancePtr;
return false;
}
delete anInstancePtr;
// if all checks done - switch to this tool
myPluginEntry = aFunc;
myDefaultName = theName;
myFunctionName = theFuncName;
myNames.Add(theName);
myDefaultName = theName;
return true;
}
//=================================================================================================
//==================================================================================================
occ::handle<BRepMesh_DiscretRoot> BRepMesh_DiscretFactory::Discret(const TopoDS_Shape& theShape,
const double theDeflection,
const double theAngle)
double theLinDeflection,
double theAngDeflection)
{
occ::handle<BRepMesh_DiscretRoot> aDiscretRoot;
BRepMesh_DiscretRoot* anInstancePtr = nullptr;
if (myPluginEntry != nullptr)
{
// use plugin
int anErr = myPluginEntry(theShape, theDeflection, theAngle, anInstancePtr);
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory =
myDefaultName.IsEmpty() ? BRepMesh_DiscretAlgoFactory::DefaultFactory()
: BRepMesh_DiscretAlgoFactory::FindFactory(myDefaultName);
if (anErr != 0 || anInstancePtr == nullptr)
{
// can not create the algo specified - should never happens here
myErrorStatus = BRepMesh_FE_CANNOTCREATEALGO;
return aDiscretRoot;
}
}
else // if (myDefaultName == THE_FAST_DISCRET_MESH)
if (aFactory.IsNull())
{
// use built-in
BRepMesh_IncrementalMesh::Discret(theShape, theDeflection, theAngle, anInstancePtr);
return occ::handle<BRepMesh_DiscretRoot>();
}
// cover with handle
aDiscretRoot = anInstancePtr;
// return the handle
return aDiscretRoot;
return aFactory->CreateAlgorithm(theShape, theLinDeflection, theAngDeflection);
}
@@ -16,20 +16,17 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <BRepMesh_PluginEntryType.hxx>
#include <BRepMesh_FactoryError.hxx>
#include <TCollection_AsciiString.hxx>
#include <NCollection_Map.hxx>
#include <OSD_Function.hxx>
#include <NCollection_DataMap.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <TCollection_AsciiString.hxx>
class TopoDS_Shape;
//! This class intended to setup / retrieve default triangulation algorithm.
//! Factory for retrieving triangulation algorithms.
//! Use BRepMesh_DiscretFactory::Get() static method to retrieve global Factory instance.
//! Use BRepMesh_DiscretFactory::Discret() method to retrieve meshing tool.
//!
//! This class delegates to BRepMesh_DiscretAlgoFactory registry for algorithm creation.
//! @sa BRepMesh_DiscretAlgoFactory
class BRepMesh_DiscretFactory
{
public:
@@ -38,65 +35,29 @@ public:
//! Returns the global factory instance.
Standard_EXPORT static BRepMesh_DiscretFactory& Get();
//! Returns the list of registered meshing algorithms.
const NCollection_Map<TCollection_AsciiString>& Names() const { return myNames; }
//! Setup meshing algorithm by name.
//! Returns TRUE if requested tool is available.
//! On fail Factory will continue to use previous algo.
bool SetDefaultName(const TCollection_AsciiString& theName)
{
return SetDefault(theName, myFunctionName);
}
//! Returns TRUE if requested algorithm is available.
//! On fail Factory will continue to use previous algorithm.
//! @param[in] theName name of the algorithm to use
Standard_EXPORT bool SetDefaultName(const TCollection_AsciiString& theName);
//! Returns name for current meshing algorithm.
//! Returns name of current meshing algorithm.
const TCollection_AsciiString& DefaultName() const { return myDefaultName; }
//! Advanced function. Changes function name to retrieve from plugin.
//! Returns TRUE if requested tool is available.
//! On fail Factory will continue to use previous algo.
bool SetFunctionName(const TCollection_AsciiString& theFuncName)
{
return SetDefault(myDefaultName, theFuncName);
}
//! Returns function name that should be exported by plugin.
const TCollection_AsciiString& FunctionName() const { return myFunctionName; }
//! Returns error status for last meshing algorithm switch.
BRepMesh_FactoryError ErrorStatus() const { return myErrorStatus; }
//! Setup meshing algorithm that should be created by this Factory.
//! Returns TRUE if requested tool is available.
//! On fail Factory will continue to use previous algo.
//! Call ::ErrorStatus() method to retrieve fault reason.
Standard_EXPORT bool SetDefault(const TCollection_AsciiString& theName,
const TCollection_AsciiString& theFuncName = "DISCRETALGO");
//! Returns triangulation algorithm instance.
//! @param theShape shape to be meshed.
//! @param theLinDeflection linear deflection to be used for meshing.
//! @param theAngDeflection angular deflection to be used for meshing.
//! @param[in] theShape shape to be meshed
//! @param[in] theLinDeflection linear deflection to be used for meshing
//! @param[in] theAngDeflection angular deflection to be used for meshing
//! @return new meshing algorithm instance, or NULL if no algorithm available
Standard_EXPORT occ::handle<BRepMesh_DiscretRoot> Discret(const TopoDS_Shape& theShape,
const double theLinDeflection,
const double theAngDeflection);
double theLinDeflection,
double theAngDeflection);
protected:
//! Constructor
Standard_EXPORT BRepMesh_DiscretFactory();
BRepMesh_DiscretFactory();
//! Destructor
Standard_EXPORT virtual ~BRepMesh_DiscretFactory();
//! Clears factory data.
Standard_EXPORT void clear();
BRepMesh_PluginEntryType myPluginEntry;
BRepMesh_FactoryError myErrorStatus;
NCollection_Map<TCollection_AsciiString> myNames;
TCollection_AsciiString myDefaultName;
TCollection_AsciiString myFunctionName;
NCollection_DataMap<TCollection_AsciiString, OSD_Function> myFactoryMethods;
TCollection_AsciiString myDefaultName;
};
#endif
@@ -1,25 +0,0 @@
// Copyright (c) 2013 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 _BRepMesh_FactoryError_HeaderFile
#define _BRepMesh_FactoryError_HeaderFile
enum BRepMesh_FactoryError
{
BRepMesh_FE_NOERROR,
BRepMesh_FE_LIBRARYNOTFOUND,
BRepMesh_FE_FUNCTIONNOTFOUND,
BRepMesh_FE_CANNOTCREATEALGO
};
#endif
@@ -16,7 +16,6 @@
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepMesh_Context.hxx>
#include <BRepMesh_PluginMacro.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshTools_MeshBuilder.hxx>
@@ -148,6 +147,3 @@ void BRepMesh_IncrementalMesh::SetParallelDefault(const bool theInParallel)
{
IS_IN_PARALLEL = theInParallel;
}
//! Export Mesh Plugin entry function
DISCRETPLUGIN(BRepMesh_IncrementalMesh)
@@ -0,0 +1,61 @@
// Copyright (c) 2025 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.
#include <BRepMesh_IncrementalMeshFactory.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMeshFactory, BRepMesh_DiscretAlgoFactory)
namespace
{
//! Self-registering factory instance
static occ::handle<BRepMesh_IncrementalMeshFactory> THE_FACTORY_INSTANCE;
//! Initialization helper that registers the factory at startup
struct FactoryInitializer
{
FactoryInitializer()
{
if (THE_FACTORY_INSTANCE.IsNull())
{
THE_FACTORY_INSTANCE = new BRepMesh_IncrementalMeshFactory();
}
}
};
static FactoryInitializer THE_FACTORY_INIT;
} // namespace
//==================================================================================================
BRepMesh_IncrementalMeshFactory::BRepMesh_IncrementalMeshFactory()
: BRepMesh_DiscretAlgoFactory("FastDiscret")
{
RegisterFactory(this, true);
}
//==================================================================================================
occ::handle<BRepMesh_DiscretRoot> BRepMesh_IncrementalMeshFactory::CreateAlgorithm(
const TopoDS_Shape& theShape,
double theLinDeflection,
double theAngDeflection)
{
occ::handle<BRepMesh_IncrementalMesh> anAlgo = new BRepMesh_IncrementalMesh();
anAlgo->ChangeParameters().Deflection = theLinDeflection;
anAlgo->ChangeParameters().Angle = theAngDeflection;
anAlgo->ChangeParameters().InParallel = BRepMesh_IncrementalMesh::IsParallelDefault();
anAlgo->SetShape(theShape);
return anAlgo;
}
@@ -0,0 +1,41 @@
// Copyright (c) 2025 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 _BRepMesh_IncrementalMeshFactory_HeaderFile
#define _BRepMesh_IncrementalMeshFactory_HeaderFile
#include <BRepMesh_DiscretAlgoFactory.hxx>
//! Factory for creating BRepMesh_IncrementalMesh instances.
//! This factory is registered under the name "FastDiscret" and provides
//! the default built-in meshing algorithm.
class BRepMesh_IncrementalMeshFactory : public BRepMesh_DiscretAlgoFactory
{
DEFINE_STANDARD_RTTIEXT(BRepMesh_IncrementalMeshFactory, BRepMesh_DiscretAlgoFactory)
public:
//! Constructor. Registers this factory under the name "FastDiscret".
Standard_EXPORT BRepMesh_IncrementalMeshFactory();
//! Creates a new BRepMesh_IncrementalMesh instance.
//! @param[in] theShape shape to be meshed
//! @param[in] theLinDeflection linear deflection for meshing
//! @param[in] theAngDeflection angular deflection for meshing
//! @return new meshing algorithm instance
Standard_EXPORT occ::handle<BRepMesh_DiscretRoot> CreateAlgorithm(
const TopoDS_Shape& theShape,
double theLinDeflection,
double theAngDeflection) override;
};
#endif // _BRepMesh_IncrementalMeshFactory_HeaderFile
@@ -1,26 +0,0 @@
// 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 _BRepMesh_PluginEntryType_HeaderFile
#define _BRepMesh_PluginEntryType_HeaderFile
class TopoDS_Shape;
class BRepMesh_DiscretRoot;
//! Type definition for plugin exported function
typedef int (*BRepMesh_PluginEntryType)(const TopoDS_Shape& theShape,
const double theLinDeflection,
const double theAngDeflection,
BRepMesh_DiscretRoot*& theMeshAlgoInstance);
#endif
@@ -1,36 +0,0 @@
// Created on: 2008-04-11
// Created by: Peter KURNEV
// Copyright (c) 2008-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 BRepMesh_PluginMacro_HeaderFile
#define BRepMesh_PluginMacro_HeaderFile
#define DISCRETPLUGIN(name) \
extern "C" \
{ \
Standard_EXPORT int DISCRETALGO(const TopoDS_Shape&, \
const double, \
const double, \
BRepMesh_DiscretRoot*&); \
} \
\
int DISCRETALGO(const TopoDS_Shape& theShape, \
const double theLinDeflection, \
const double theAngDeflection, \
BRepMesh_DiscretRoot*& theAlgo) \
{ \
return name::Discret(theShape, theLinDeflection, theAngDeflection, theAlgo); \
}
#endif
@@ -34,10 +34,14 @@ set(OCCT_BRepMesh_FILES
BRepMesh_DelaunayBaseMeshAlgo.hxx
BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx
BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx
BRepMesh_DiscretAlgoFactory.cxx
BRepMesh_DiscretAlgoFactory.hxx
BRepMesh_DiscretFactory.cxx
BRepMesh_DiscretFactory.hxx
BRepMesh_DiscretRoot.cxx
BRepMesh_DiscretRoot.hxx
BRepMesh_IncrementalMeshFactory.cxx
BRepMesh_IncrementalMeshFactory.hxx
BRepMesh_Edge.hxx
BRepMesh_EdgeDiscret.cxx
BRepMesh_EdgeDiscret.hxx
@@ -50,7 +54,6 @@ set(OCCT_BRepMesh_FILES
BRepMesh_FaceChecker.hxx
BRepMesh_FaceDiscret.cxx
BRepMesh_FaceDiscret.hxx
BRepMesh_FactoryError.hxx
BRepMesh_FastDiscret.hxx
BRepMesh_GeomTool.cxx
BRepMesh_GeomTool.hxx
@@ -73,8 +76,6 @@ set(OCCT_BRepMesh_FILES
BRepMesh_NodeInsertionMeshAlgo.hxx
BRepMesh_OrientedEdge.hxx
BRepMesh_PairOfIndex.hxx
BRepMesh_PluginEntryType.hxx
BRepMesh_PluginMacro.hxx
BRepMesh_SelectorOfDataStructureOfDelaun.cxx
BRepMesh_SelectorOfDataStructureOfDelaun.hxx
BRepMesh_ShapeTool.cxx
@@ -0,0 +1,145 @@
// Copyright (c) 2025 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.
#include <gtest/gtest.h>
#include <BRepMesh_DiscretAlgoFactory.hxx>
#include <BRepMesh_DiscretFactory.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <TopoDS_Shape.hxx>
//! Test fixture for BRepMesh_DiscretAlgoFactory tests
class BRepMesh_DiscretAlgoFactoryTest : public testing::Test
{
protected:
void SetUp() override
{
// Create a simple box shape for testing
BRepPrimAPI_MakeBox aBoxMaker(10.0, 10.0, 10.0);
myBox = aBoxMaker.Shape();
}
TopoDS_Shape myBox;
};
//! Test that at least one factory is registered (FastDiscret from BRepMesh_IncrementalMeshFactory)
TEST_F(BRepMesh_DiscretAlgoFactoryTest, Factories_AtLeastOneRegistered)
{
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories =
BRepMesh_DiscretAlgoFactory::Factories();
EXPECT_FALSE(aFactories.IsEmpty()) << "No factories registered";
}
//! Test that DefaultFactory returns a valid factory
TEST_F(BRepMesh_DiscretAlgoFactoryTest, DefaultFactory_ReturnsValid)
{
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory = BRepMesh_DiscretAlgoFactory::DefaultFactory();
EXPECT_FALSE(aFactory.IsNull()) << "DefaultFactory returned null";
}
//! Test that FastDiscret factory is registered and can be found
TEST_F(BRepMesh_DiscretAlgoFactoryTest, FindFactory_FastDiscret)
{
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory =
BRepMesh_DiscretAlgoFactory::FindFactory("FastDiscret");
EXPECT_FALSE(aFactory.IsNull()) << "FastDiscret factory not found";
if (!aFactory.IsNull())
{
EXPECT_EQ(aFactory->Name(), "FastDiscret");
}
}
//! Test that FindFactory returns null for non-existent factory
TEST_F(BRepMesh_DiscretAlgoFactoryTest, FindFactory_NonExistent_ReturnsNull)
{
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory =
BRepMesh_DiscretAlgoFactory::FindFactory("NonExistentFactory");
EXPECT_TRUE(aFactory.IsNull()) << "FindFactory should return null for non-existent factory";
}
//! Test that CreateAlgorithm creates a valid algorithm
TEST_F(BRepMesh_DiscretAlgoFactoryTest, CreateAlgorithm_ReturnsValid)
{
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory = BRepMesh_DiscretAlgoFactory::DefaultFactory();
ASSERT_FALSE(aFactory.IsNull());
occ::handle<BRepMesh_DiscretRoot> anAlgo = aFactory->CreateAlgorithm(myBox, 0.1, 0.5);
EXPECT_FALSE(anAlgo.IsNull()) << "CreateAlgorithm returned null";
}
//! Test that created algorithm can mesh a shape
TEST_F(BRepMesh_DiscretAlgoFactoryTest, CreateAlgorithm_CanMesh)
{
occ::handle<BRepMesh_DiscretAlgoFactory> aFactory = BRepMesh_DiscretAlgoFactory::DefaultFactory();
ASSERT_FALSE(aFactory.IsNull());
occ::handle<BRepMesh_DiscretRoot> anAlgo = aFactory->CreateAlgorithm(myBox, 0.1, 0.5);
ASSERT_FALSE(anAlgo.IsNull());
anAlgo->Perform();
EXPECT_TRUE(anAlgo->IsDone()) << "Meshing failed";
}
//! Test that BRepMesh_DiscretFactory::Discret uses the new registry
TEST_F(BRepMesh_DiscretAlgoFactoryTest, DiscretFactory_UsesRegistry)
{
BRepMesh_DiscretFactory& aFactory = BRepMesh_DiscretFactory::Get();
occ::handle<BRepMesh_DiscretRoot> anAlgo = aFactory.Discret(myBox, 0.1, 0.5);
EXPECT_FALSE(anAlgo.IsNull()) << "Discret returned null";
if (!anAlgo.IsNull())
{
anAlgo->Perform();
EXPECT_TRUE(anAlgo->IsDone()) << "Meshing failed";
}
}
//! Test that SetDefaultName works with registry-based factories
TEST_F(BRepMesh_DiscretAlgoFactoryTest, DiscretFactory_SetDefaultName)
{
BRepMesh_DiscretFactory& aFactory = BRepMesh_DiscretFactory::Get();
bool isSuccess = aFactory.SetDefaultName("FastDiscret");
EXPECT_TRUE(isSuccess) << "SetDefaultName(FastDiscret) failed";
EXPECT_EQ(aFactory.DefaultName(), "FastDiscret");
}
//! Test factory name uniqueness - registering same factory twice should not duplicate
TEST_F(BRepMesh_DiscretAlgoFactoryTest, RegisterFactory_Uniqueness)
{
const NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>& aFactories =
BRepMesh_DiscretAlgoFactory::Factories();
// Count factories with name "FastDiscret"
int aCount = 0;
for (NCollection_List<occ::handle<BRepMesh_DiscretAlgoFactory>>::Iterator anIter(aFactories);
anIter.More();
anIter.Next())
{
if (anIter.Value()->Name() == "FastDiscret")
{
++aCount;
}
}
EXPECT_EQ(aCount, 1) << "FastDiscret factory should be registered exactly once";
}
@@ -3,5 +3,6 @@ set(OCCT_TKMesh_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
set(OCCT_TKMesh_GTests_FILES
BRepMesh_Delaun_Test.cxx
BRepMesh_DiscretAlgoFactory_Test.cxx
BRepMesh_GeomTool_Test.cxx
)
@@ -2,6 +2,6 @@
set(OCCT_XBRepMesh_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
set(OCCT_XBRepMesh_FILES
XBRepMesh.cxx
XBRepMesh.hxx
XBRepMesh_Factory.cxx
XBRepMesh_Factory.hxx
)
@@ -1,38 +0,0 @@
// Created on: 2008-04-11
// Created by: Peter KURNEV
// Copyright (c) 2008-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.
#include <XBRepMesh.hxx>
#include <BRepMesh_PluginMacro.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
//=================================================================================================
int XBRepMesh::Discret(const TopoDS_Shape& theShape,
const double theDeflection,
const double theAngle,
BRepMesh_DiscretRoot*& theAlgo)
{
int iErr;
//
iErr = 0;
BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh;
anAlgo->ChangeParameters().Deflection = theDeflection;
anAlgo->ChangeParameters().Angle = theAngle;
anAlgo->SetShape(theShape);
theAlgo = anAlgo;
return iErr;
}
DISCRETPLUGIN(XBRepMesh)
@@ -1,37 +0,0 @@
// Created on: 2008-04-11
// Created by: Peter KURNEV
// Copyright (c) 2008-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 _XBRepMesh_HeaderFile
#define _XBRepMesh_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <BRepMesh_DiscretRoot.hxx>
class TopoDS_Shape;
class XBRepMesh
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT static int Discret(const TopoDS_Shape& theShape,
const double theDeflection,
const double theAngle,
BRepMesh_DiscretRoot*& theAlgo);
};
#endif
@@ -0,0 +1,59 @@
// Copyright (c) 2025 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.
#include <XBRepMesh_Factory.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
IMPLEMENT_STANDARD_RTTIEXT(XBRepMesh_Factory, BRepMesh_DiscretAlgoFactory)
namespace
{
//! Self-registering factory instance
static occ::handle<XBRepMesh_Factory> THE_FACTORY_INSTANCE;
//! Initialization helper that registers the factory at startup
struct FactoryInitializer
{
FactoryInitializer()
{
if (THE_FACTORY_INSTANCE.IsNull())
{
THE_FACTORY_INSTANCE = new XBRepMesh_Factory();
}
}
};
static FactoryInitializer THE_FACTORY_INIT;
} // namespace
//==================================================================================================
XBRepMesh_Factory::XBRepMesh_Factory()
: BRepMesh_DiscretAlgoFactory("XBRepMesh")
{
RegisterFactory(this);
}
//==================================================================================================
occ::handle<BRepMesh_DiscretRoot> XBRepMesh_Factory::CreateAlgorithm(const TopoDS_Shape& theShape,
double theLinDeflection,
double theAngDeflection)
{
occ::handle<BRepMesh_IncrementalMesh> anAlgo = new BRepMesh_IncrementalMesh();
anAlgo->ChangeParameters().Deflection = theLinDeflection;
anAlgo->ChangeParameters().Angle = theAngDeflection;
anAlgo->SetShape(theShape);
return anAlgo;
}
@@ -0,0 +1,41 @@
// Copyright (c) 2025 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 _XBRepMesh_Factory_HeaderFile
#define _XBRepMesh_Factory_HeaderFile
#include <BRepMesh_DiscretAlgoFactory.hxx>
//! Factory for creating XBRepMesh meshing algorithm instances.
//! This factory is registered under the name "XBRepMesh" and provides
//! an alternative meshing algorithm based on BRepMesh_IncrementalMesh.
class XBRepMesh_Factory : public BRepMesh_DiscretAlgoFactory
{
DEFINE_STANDARD_RTTIEXT(XBRepMesh_Factory, BRepMesh_DiscretAlgoFactory)
public:
//! Constructor. Registers this factory under the name "XBRepMesh".
Standard_EXPORT XBRepMesh_Factory();
//! Creates a new meshing algorithm instance.
//! @param[in] theShape shape to be meshed
//! @param[in] theLinDeflection linear deflection for meshing
//! @param[in] theAngDeflection angular deflection for meshing
//! @return new meshing algorithm instance
Standard_EXPORT occ::handle<BRepMesh_DiscretRoot> CreateAlgorithm(
const TopoDS_Shape& theShape,
double theLinDeflection,
double theAngDeflection) override;
};
#endif // _XBRepMesh_Factory_HeaderFile