From 8a43b951e89760d244733514655ab0746c055b81 Mon Sep 17 00:00:00 2001 From: mbs Date: Wed, 13 Nov 2024 09:35:20 +0000 Subject: [PATCH] [bos #43130] [EDF] (2024) Geometry Analysis Tool --- idl/GEOM_Gen.idl | 19 +++ src/GEOMImpl/CMakeLists.txt | 21 +++ src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx | 128 +++++++++++++++++++ src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx | 9 ++ src/GEOM_I/GEOM_IMeasureOperations_i.cc | 53 ++++++++ src/GEOM_I/GEOM_IMeasureOperations_i.hh | 9 ++ src/GEOM_SWIG/geomBuilder.py | 34 +++++ 7 files changed, 273 insertions(+) diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 1d6abe8c3..d4d2eed32 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -4797,6 +4797,25 @@ module GEOM string PrintShapeErrors (in GEOM_Object theShape, in ShapeErrors theErrors); + // /*! + // * \brief Extract and identify any problem in the source shapes used in a Boolean Operation. + // * \param theShapes Shapes being used in the Boolean Operation + // * \param theUseTimer Whether to chronometrize computation time + // * \param theTopoOnly Whether to check topology only + // * \param theShortReport Whether to display the error report in short format + // * \param theRunParallel Whether to run the computations in parallel + // * \param theDoExact Whether to perform exact checking + // * \param theErrors Structure, containing discovered errors and incriminated sub-shapes. + // * \return TRUE, if the input shapes "seem to be valid" for BOP. + // */ + boolean ExtractBOPFailure (in ListOfGO theShapes, + in boolean theUseTimer, + in boolean theTopoOnly, + in boolean theShortReport, + in boolean theRunParallel, + in boolean theDoExact, + out ShapeErrors theErrors); + /*! * \brief Check a topology of the given shape on self-intersections presence. * \param theShape Shape to check validity of. diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index 64228aa7c..1f24e459a 100644 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -17,6 +17,17 @@ # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # +## FIXME +SET(COMMONGEOMLIB_ROOT_DIR "/hdd2/S2/SALOME-MBS-DB11/INSTALL/CommonGeomLib") +## +message(STATUS "COMMONGEOMLIB_ROOT_DIR: ${COMMONGEOMLIB_ROOT_DIR}") +SET(COMMONGEOMLIB_INCLUDE_DIR "${COMMONGEOMLIB_ROOT_DIR}/${SALOME_INSTALL_HEADERS}") +SET(COMMONGEOMLIB_LIBRARY_DIR "${COMMONGEOMLIB_ROOT_DIR}/${SALOME_INSTALL_LIBS}") +SET(COMMOMGEOMLIB_LIBRARIES GeomAnaTool) +message(STATUS "COMMONGEOMLIB_INCLUDE_DIR: ${COMMONGEOMLIB_INCLUDE_DIR}") +message(STATUS "COMMONGEOMLIB_LIBRARY_DIR: ${COMMONGEOMLIB_LIBRARY_DIR}") +message(STATUS "COMMOMGEOMLIB_LIBRARIES: ${COMMOMGEOMLIB_LIBRARIES}") + # --- options --- # additional include directories @@ -26,6 +37,7 @@ INCLUDE_DIRECTORIES( ${KERNEL_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIR} + ${COMMONGEOMLIB_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/src/ShHealOper ${PROJECT_SOURCE_DIR}/src/GEOM ${PROJECT_SOURCE_DIR}/src/BlockFix @@ -45,7 +57,16 @@ ADD_DEFINITIONS( ) # libraries to link to +message(STATUS "----------------------------------------") +message(STATUS "COMMONGEOMLIB_LIBRARIES: ${COMMOMGEOMLIB_LIBRARIES}") +message(STATUS "OpenCASCADE_ModelingAlgorithms_LIBRARIES: ${OpenCASCADE_ModelingAlgorithms_LIBRARIES}") +message(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}") +message(STATUS "KERNEL_SALOMELocalTrace: ${KERNEL_SALOMELocalTrace}") +message(STATUS "----------------------------------------") SET(_link_LIBRARIES + ##FIXME: + ## The following line works only for Linux, not for Windows + ${COMMONGEOMLIB_LIBRARY_DIR}/libGeomAnaTool.so ${OpenCASCADE_ModelingAlgorithms_LIBRARIES} ${PYTHON_LIBRARIES} ShHealOper GEOMbasic BlockFix GEOMAlgo GEOMUtils GEOMSketcher GEOMArchimede XAO diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index 56d5d592b..11c27b534 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -46,6 +46,10 @@ #include +// CommonGeomLib Includes +#include +#include + // OCCT Includes #include #include @@ -1713,6 +1717,130 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors return aDump; } + +//============================================================================= +/*! + * ExtractBOPFailure + */ +//============================================================================= +bool GEOMImpl_IMeasureOperations::ExtractBOPFailure + (const Handle(TColStd_HSequenceOfTransient)& theShapes, + const bool theUseTimer, + const bool theTopoOnly, + const bool theShortReport, + const bool theRunParallel, + const bool theDoExact, + std::list& theErrors) +{ + SetErrorCode(KO); + theErrors.clear(); + + if (theShapes.IsNull()) return false; + + Standard_Integer aNbShapes = theShapes->Length(); + if (!aNbShapes) return false; + + TopTools_ListOfShape aList; + for (int i=1; i<=aNbShapes; i++) { + Handle(GEOM_Object) aGeomObj = Handle(GEOM_Object)::DownCast(theShapes->Value(i)); + if (aGeomObj.IsNull()) + continue; + + Handle(GEOM_Function) aRefShape = aGeomObj->GetLastFunction(); + if (aRefShape.IsNull()) + continue; + + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) + continue; + + aList.Append(aShape); + } + + // Call the GeomAnaTool API to extract BOP failures + // TopTools_ListOfShape aFailuresList = GeomAnaTool::ExtractBOPFailure(aList, theUseTimer, theTopoOnly, theShortReport, theRunParallel, theDoExact); + // std::cout << "ExtractBOPFailure: " << aFailuresList.Extent() << " failures" << std::endl; + + //TopTools_ListOfShape aResult; + bool isValid = false; + try + { + OCC_CATCH_SIGNALS; + GeomAnaTool_ExtractBOPFailure aTool(aList); + aTool.SetUseTimer(theUseTimer); + aTool.SetCheckGeometry(!theTopoOnly); // Either topo only or topo+geometry + aTool.SetShortOutput(theShortReport); + aTool.SetRunParallel(theRunParallel); + aTool.SetExactCheck(theDoExact); + aTool.Perform(); + if (aTool.HasFailures()) + { + std::cout << "--- The operation has failures ---" << std::endl; + //aResult = aTool.Failures(); + //std::cout << "#Failures = " << aResult.Extent() << std::endl; + const std::list& errors = aTool.ShapeErrors(); + std::cout << "#Failures = " << errors.size() << std::endl; + for (std::list::const_iterator it = errors.begin(); it != errors.end(); ++it) + { + ShapeError aError; + aError.error = it->error; + aError.incriminated = it->incriminated; + theErrors.push_back(aError); + } + } + else + { + std::cout << "+++ The operation has no failures +++" << std::endl; + isValid = true; + } + } + catch(Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + std::cout << "Exception: " << GetErrorCode() << std::endl; + return false; + } + + // Handle(TColStd_HSequenceOfTransient) aFailures = new TColStd_HSequenceOfTransient; + // + // // Convert each failure shape to a GEOM_Object and add to the sequence + // Handle(GEOM_Object) aFailureObj = GetEngine()->AddObject(GEOM_BOP_FAILURE); + // if (!aFailureObj.IsNull()) + // { + // for (TopTools_ListIteratorOfListOfShape it(aFailuresList); it.More(); it.Next()) { + // TopoDS_Shape aFailureShape = it.Value(); + // + // Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aFailureObj, anArray); + // if (!anObj.IsNull()) + // { + // aFailures->Append(anObj); + // } + // } + // } + + // // Get result compound and collect all subshapes into result sequence + // TopoDS_Shape aResCompound = aFunction->GetValue(); + // TopTools_IndexedMapOfShape anIndices; + // TopExp::MapShapes(aResCompound, anIndices); + + // Handle(TColStd_HArray1OfInteger) anArray; + // for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next()) + // { + // TopoDS_Shape aValue = anExpW.Value(); + // anArray = new TColStd_HArray1OfInteger(1, 1); + // anArray->SetValue(1, anIndices.FindIndex(aValue)); + + // Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray); + // if (!anObj.IsNull()) + // { + // aSeq->Append(anObj); + // } + // } + + SetErrorCode(OK); + return isValid; +} + //============================================================================= /*! * CheckSelfIntersections diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx index e13d8a5e7..8b677de56 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx @@ -162,6 +162,15 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations { (Handle(GEOM_Object) theShape, const std::list &theErrors); + Standard_EXPORT bool ExtractBOPFailure + (const Handle(TColStd_HSequenceOfTransient)& theShapes, + const bool theUseTimer, + const bool theTopoOnly, + const bool theShortReport, + const bool theRunParallel, + const bool theDoExact, + std::list& theErrors); + Standard_EXPORT bool CheckSelfIntersections (Handle(GEOM_Object) theShape, const SICheckLevel theCheckLevel, Handle(TColStd_HSequenceOfInteger)& theIntersections); diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.cc b/src/GEOM_I/GEOM_IMeasureOperations_i.cc index 0acbdb36c..1feb907c8 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.cc +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.cc @@ -22,6 +22,7 @@ #include #include +#include #include "GEOM_IMeasureOperations_i.hh" @@ -709,6 +710,58 @@ char* GEOM_IMeasureOperations_i::PrintShapeErrors return CORBA::string_dup(aDescr.ToCString()); } +//============================================================================= +/*! + * ExtractBOPFailure + */ +//============================================================================= +CORBA::Boolean GEOM_IMeasureOperations_i::ExtractBOPFailure + (const GEOM::ListOfGO& theShapes, + CORBA::Boolean theUseTimer, + CORBA::Boolean theTopoOnly, + CORBA::Boolean theShortReport, + CORBA::Boolean theRunParallel, + CORBA::Boolean theDoExact, + GEOM::GEOM_IMeasureOperations::ShapeErrors_out theErrors) +{ + // Set the not done flag + GetOperations()->SetNotDone(); + + // Check for existing shapes + int aNbShapes = theShapes.length(); + if (!aNbShapes) + { + return 0; + } + + // Create the sequence of GEOM objects for the failure shapes + GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO; + Handle(TColStd_HSequenceOfTransient) aSeqShapes = new TColStd_HSequenceOfTransient; + for (int i = 0; i < aNbShapes; i++) + { + Handle(::GEOM_Object) aShape = GetObjectImpl(theShapes[i]); + if (!aShape.IsNull()) + { + aSeqShapes->Append(aShape); + } + } + + if (!aSeqShapes->Length()) + { + return 0; + } + + // Perform partition operation and check for failures + std::list anErrList; + bool isOk = GetOperations()->ExtractBOPFailure(aSeqShapes, theUseTimer, theTopoOnly, + theShortReport, theRunParallel, theDoExact, + anErrList); + + ConvertShapeError(anErrList, theErrors); + + return isOk; +} + //============================================================================= /*! * CheckSelfIntersections diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.hh b/src/GEOM_I/GEOM_IMeasureOperations_i.hh index e1cd715ad..3b346e796 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.hh +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.hh @@ -98,6 +98,15 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i : ( GEOM::GEOM_Object_ptr theShape, const GEOM::GEOM_IMeasureOperations::ShapeErrors &theErrors); + CORBA::Boolean ExtractBOPFailure + (const GEOM::ListOfGO& theShapes, + CORBA::Boolean theUseTimer, + CORBA::Boolean theTopoOnly, + CORBA::Boolean theShortReport, + CORBA::Boolean theRunParallel, + CORBA::Boolean theDoExact, + GEOM::GEOM_IMeasureOperations::ShapeErrors_out theErrors); + CORBA::Boolean CheckSelfIntersections (GEOM::GEOM_Object_ptr theShape, CORBA::Long theCheckLevel, GEOM::ListOfLong_out theIntersections); diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index e9cf78b47..04cad8817 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -11982,6 +11982,40 @@ class geomBuilder(GEOM._objref_GEOM_Gen): """ return self.MeasuOp.CheckBOPArguments(theShape) + + def ExtractBOPFailure(self, lFaces, timer=None, topo=None, short=None, parallel=None, exact=None): + """ + Extracts the BOP failure information from the given list of faces. + + Parameters: + lFaces - list of faces to extract the BOP failure information from. + timer - if True, the time of the operation is measured. + topo - if True, only the topological entities will be checked. + short - if True, the error report will be in short format. + parallel - if True, the operation will be executed in parallel. + exact - if True, an exact check will be performed. + + Returns: + the list of failed shapes. + """ + # Check for default parameter values + if timer is None: + timer = False # default: do not measure execution time + if topo is None: + topo = False # default: check geometry & topology + if short is None: + short = False # default: show full error report + if parallel is None: + parallel = False # default: run operation sequentially + if exact is None: + exact = False # default: do not perform exact check + # (IsValid, ShapeErrors) = self.MeasuOp.ExtractBOPFailure(lFaces, timer, topo, short, parallel, exact) + # if IsValid == 0: + # Descr = self.MeasuOp.PrintShapeErrors(lFaces[0], ShapeErrors) + # print(Descr) + # return IsValid + return self.MeasuOp.ExtractBOPFailure(lFaces, timer, topo, short, parallel, exact) + ## Detect intersections of the given shapes with algorithm based on mesh intersections. # @param theShape1 First source object # @param theShape2 Second source object -- 2.39.2