[bos #43130] [EDF] (2024) Geometry Analysis Tool

This commit is contained in:
mbs 2024-11-13 09:35:20 +00:00 committed by jfa
parent 4698ac46c4
commit 1e56cfc237
27 changed files with 907 additions and 224 deletions

View File

@ -140,6 +140,13 @@ ENDIF(SALOME_BUILD_GUI)
FIND_PACKAGE(SalomeOpenCASCADE REQUIRED)
SET(CommonGeomLib_ROOT_DIR $ENV{CommonGeomLib_ROOT_DIR} CACHE PATH "Path to the CommonGeomLib tool")
IF(EXISTS ${CommonGeomLib_ROOT_DIR})
FIND_PACKAGE(SalomeCommonGeomLib REQUIRED)
ELSE(EXISTS ${CommonGeomLib_ROOT_DIR})
MESSAGE(FATAL_ERROR "We absolutely need the CommonGeomLib tool, please define CommonGeomLib_ROOT_DIR !")
ENDIF(EXISTS ${CommonGeomLib_ROOT_DIR})
IF(SALOME_GEOM_USE_VTK)
FIND_PACKAGE(SalomeVTK REQUIRED)
ADD_DEFINITIONS(-DWITH_VTK)
@ -279,19 +286,21 @@ EXPORT(TARGETS ${_${PROJECT_NAME}_exposed_targets}
SET(KERNEL_ROOT_DIR "${KERNEL_ROOT_DIR}")
SET(GUI_ROOT_DIR "${GUI_ROOT_DIR}")
SET(OPENCASCADE_ROOT_DIR "${OPENCASCADE_ROOT_DIR}")
SET(CommonGeomLib_ROOT_DIR "${CommonGeomLib_ROOT_DIR}")
SET(VTK_ROOT_DIR "${VTK_ROOT_DIR}")
SET(OPENCV_ROOT_DIR "${OPENCV_ROOT_DIR}")
SET(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include" "${PROJECT_BINARY_DIR}/include")
# Build variables that will be expanded when configuring Salome<MODULE>Config.cmake:
SALOME_CONFIGURE_PREPARE(OpenCV OpenCASCADE VTK)
SALOME_CONFIGURE_PREPARE(OpenCV OpenCASCADE CommonGeomLib VTK)
CONFIGURE_PACKAGE_CONFIG_FILE(${PROJECT_NAME}Config.cmake.in
${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION "${SALOME_INSTALL_CMAKE_LOCAL}"
PATH_VARS CONF_INCLUDE_DIRS SALOME_INSTALL_CMAKE_LOCAL CMAKE_INSTALL_PREFIX
KERNEL_ROOT_DIR GUI_ROOT_DIR OPENCASCADE_ROOT_DIR VTK_ROOT_DIR OPENCV_ROOT_DIR)
KERNEL_ROOT_DIR GUI_ROOT_DIR OPENCASCADE_ROOT_DIR CommonGeomLib_ROOT_DIR
VTK_ROOT_DIR OPENCV_ROOT_DIR)
# - in the install tree (VSR 16/08/2013: TEMPORARILY COMMENT THIS - TO REMOVE?):
# Get the relative path of the include directory so

View File

@ -0,0 +1,56 @@
# ExtractBOPFailure example
import math
import salome
salome.salome_init()
import GEOM
from salome.geom import geomBuilder
geompy = geomBuilder.New()
### Prepare shapes for Partition
OX = geompy.MakeVectorDXDYDZ(1, 0, 0, theName="OX")
OY = geompy.MakeVectorDXDYDZ(0, 1, 0, theName="OY")
OZ = geompy.MakeVectorDXDYDZ(0, 0, 1, theName="OZ")
Vertex_1 = geompy.MakeVertex(0, 0, 0, theName="Vertex_1")
Vertex_2 = geompy.MakeVertex(10, 0, 0, theName="Vertex_2")
Vertex_3 = geompy.MakeVertex(0, 0.005, 0, theName="Vertex_3")
Vertex_4 = geompy.MakeVertex(10, 0.015, 0, theName="Vertex_4")
Vertex_5 = geompy.MakeVertex(0, 0.02, 0, theName="Vertex_5")
Vertex_6 = geompy.MakeVertex(10, 0.02, 0, theName="Vertex_6")
Line_1 = geompy.MakeLineTwoPnt(Vertex_1, Vertex_2, theName="Line_1")
Line_2 = geompy.MakeLineTwoPnt(Vertex_3, Vertex_4, theName="Line_2")
Line_3 = geompy.MakeLineTwoPnt(Vertex_5, Vertex_6, theName="Line_3")
Extrusion_1 = geompy.MakePrismVecH(Line_1, OY, 1, theName="Extrusion_1")
Extrusion_2 = geompy.MakePrismVecH(Line_2, OZ, 1, theName="Extrusion_2")
Extrusion_3 = geompy.MakePrismVecH(Line_3, OY, -1, theName="Extrusion_3")
Limit_tolerance_1 = geompy.LimitTolerance(Extrusion_2, 0.01, theName="Limit_tolerance_1")
Extrusion_4 = geompy.MakePrismVecH(Extrusion_1, OZ, -1, theName="Extrusion_4")
Extrusion_5 = geompy.MakePrismVecH(Extrusion_3, OZ, -1, theName="Extrusion_5")
Revolution_1 = geompy.MakeRevolution(Limit_tolerance_1, OX, 45*math.pi/180.0, theName="Revolution_1")
### Try Partition
try :
Partition_1 = geompy.MakePartition([Extrusion_4, Extrusion_5, Revolution_1], [], [], [], geompy.ShapeType["SOLID"], 0, [], 0, theName="Partition_1")
except :
print("EXCEPTION: Partition problem")
### Extract failures
(IsValid, ShapeRes, ShapeErrors) = geompy.ExtractBOPFailure([Extrusion_4, Extrusion_5, Revolution_1], theTimer=True, theVerbose=True, theName="InvalidBOPResult")
### Publish incriminated sub-shapes (reflect errors in their names)
for shapeError in ShapeErrors:
list_ids = shapeError.incriminated
list_subs = geompy.SubShapes(ShapeRes, list_ids)
ii = 1
for subshape in list_subs:
geompy.addToStudyInFather( ShapeRes, subshape, 'SubShape_with_%s_%d'%(str(shapeError.error),ii) )
ii = ii+1
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

View File

@ -58,6 +58,8 @@ SET(GOOD_TESTS
check_compound_of_blocks.py
check_self_intersections.py
check_shape.py
check_conformity.py
check_bop.py
complex_objs_ex01.py
complex_objs_ex02.py
complex_objs_ex03.py

View File

@ -0,0 +1,32 @@
/*!
\page check_bop_page Extract BOP Failure
The Extract BOP Failure tool makes it possible to analyse a BOP or Partition failure, in case the result is invalid. \n
It performs the general fuse BOP and returns the resulting shape and the list of errors from Check Shape point of view.
This is a TUI-only functionality.
<b>TUI Command:</b>
<UL>
<LI>
<em>(IsValid, ShapeRes, ShapeErrors) = geompy.ExtractBOPFailure(theShapes, theTimer=False, theTopo=False, theParallel=False, theExact=False, theVerbose=True),</em> \n
where \n
\em theShapes is the list of argument shapes for BOP. \n
\em theTimer - if True, the time of the operation is measured. \n
\em theTopo - if True, only the topological entities will be checked, otherwise geometry and topology are checked. \n
\em theParallel - if True, the operation will be executed in parallel. \n
\em theExact - if True, an exact check will be performed. \n
\em theVerbose - if True, prints execution errors and check results. \n
\em Returns: \n
\em IsValid - a boolean value (whether result shape is valid or not) \n
\em ShapeRes - the result shape itself \n
\em ShapeErrors - the list of GEOM.GEOM_IMeasureOperations.ShapeError \n
</LI>
</UL>
See also a \ref tui_check_bop_page "TUI example".
*/

View File

@ -0,0 +1,6 @@
/*!
\page tui_check_bop_page Extract BOP Failure
\tui_script{check_bop.py}
*/

View File

@ -22,6 +22,7 @@
<li>\subpage tui_check_self_intersections_fast_page</li>
<li>\subpage tui_fast_intersection_page</li>
<li>\subpage tui_check_conformity_page</li>
<li>\subpage tui_check_bop_page</li>
<li>\subpage tui_shape_proximity_page</li>
<li>\subpage tui_xyz_to_uv_page</li>
<li>\subpage tui_kind_of_shape_page</li>

View File

@ -31,6 +31,7 @@
<li>\subpage free_faces_page "Check Free Faces"</li>
<li>\subpage check_shape_page "Check Shape"</li>
<li>\subpage check_conformity_page "Check Conformity"</li>
<li>\subpage check_bop_page "Extract BOP Failures"</li>
<li>\subpage check_compound_of_blocks_page "Check compound of blocks"</li>
<li>\subpage get_non_blocks_page "Get non blocks"</li>
<li>\subpage check_self_intersections_page "Detect Self-intersections"</li>

View File

@ -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 theRunParallel Whether to run the computations in parallel
// * \param theDoExact Whether to perform exact checking
// * \param theResultShape Output parameter. The result of BOP General Fuse. Indices of its sub-shapes are reported in theErrors structure.
// * \param theErrors Output parameter. 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 theRunParallel,
in boolean theDoExact,
out GEOM_Object theResultShape,
out ShapeErrors theErrors);
/*!
* \brief Check a topology of the given shape on self-intersections presence.
* \param theShape Shape to check validity of.

View File

@ -25,6 +25,7 @@ INCLUDE_DIRECTORIES(
${PTHREAD_INCLUDE_DIR}
${OpenCASCADE_INCLUDE_DIR}
${KERNEL_INCLUDE_DIRS}
${CommonGeomLib_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/GEOMImpl
${PROJECT_SOURCE_DIR}/src/GEOM
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -22,6 +22,7 @@
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${PTHREAD_INCLUDE_DIR}
${KERNEL_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
@ -46,6 +47,7 @@ ADD_DEFINITIONS(
# libraries to link to
SET(_link_LIBRARIES
${CommonGeomLib_GeomAnaTool}
${OpenCASCADE_ModelingAlgorithms_LIBRARIES}
${PYTHON_LIBRARIES}
ShHealOper GEOMbasic BlockFix GEOMAlgo GEOMUtils GEOMSketcher GEOMArchimede XAO

View File

@ -34,6 +34,9 @@
#include <GEOMImpl_IConformity.hxx>
#include <GEOMImpl_ConformityDriver.hxx>
#include <GEOMImpl_IPartition.hxx>
#include <GEOMImpl_PartitionDriver.hxx>
#include <GEOMUtils.hxx>
#include <GEOMAlgo_AlgoTools.hxx>
@ -46,6 +49,10 @@
#include <Basics_OCCTVersion.hxx>
// CommonGeomLib Includes
#include <GeomAnaTool_Tools.hxx>
#include <GeomAnaTool_ExtractBOPFailure.hxx>
// OCCT Includes
#include <Bnd_Box.hxx>
#include <BOPAlgo_CheckerSI.hxx>
@ -176,7 +183,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
theDoubles->Append(aC.X());
theDoubles->Append(aC.Y());
theDoubles->Append(aC.Z());
gp_Dir aD = anAx3.XDirection();
theDoubles->Append(aD.X());
theDoubles->Append(aD.Y());
@ -580,7 +587,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape
{
// (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices
aKind = SK_PLANAR;
theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE));
theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX));
}
@ -1376,7 +1383,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox
//Make a Python command
GEOM::TPythonDump aPd(aFunction);
aPd << aBnd << " = geompy.MakeBoundingBox(" << theShape;
if (precise) {
@ -1460,7 +1467,7 @@ void GEOMImpl_IMeasureOperations::GetTolerance
//=============================================================================
bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
const Standard_Boolean theIsCheckGeom,
std::list<ShapeError> &theErrors)
std::list<GeomAnaTool::ShapeError> &theErrors)
{
SetErrorCode(KO);
theErrors.clear();
@ -1484,7 +1491,7 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
if (ana.IsValid()) {
isValid = true;
} else {
FillErrors(ana, aShape, theErrors);
GeomAnaTool::FillErrors(ana, aShape, theErrors);
}
}
catch (Standard_Failure& aFail) {
@ -1503,7 +1510,7 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape,
//=============================================================================
TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
(Handle(GEOM_Object) theShape,
const std::list<ShapeError> &theErrors)
const std::list<GeomAnaTool::ShapeError> &theErrors)
{
TCollection_AsciiString aDump;
@ -1527,7 +1534,7 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::PrintShapeErrors
if (!theErrors.empty()) {
// The shape is not valid. Prepare errors for dump.
TopTools_IndexedMapOfShape anIndices;
std::list<ShapeError>::const_iterator anIter = theErrors.begin();
std::list<GeomAnaTool::ShapeError>::const_iterator anIter = theErrors.begin();
Standard_Integer nbv, nbe, nbw, nbf, nbs, nbo;
nbv = nbe = nbw = nbf = nbs = nbo = 0;
@ -1713,6 +1720,111 @@ 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 theRunParallel,
const bool theDoExact,
Handle(GEOM_Object)& theResultShape,
std::list<GeomAnaTool::ShapeError>& theErrors)
{
SetErrorCode(OK);
theErrors.clear();
if (theShapes.IsNull()) return false;
Standard_Integer aNbShapes = theShapes->Length();
if (!aNbShapes) return false;
Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
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;
aShapesSeq->Append(aRefShape);
aList.Append(aShape);
}
// Call the GeomAnaTool API to extract BOP failures
bool isValid = false;
try
{
OCC_CATCH_SIGNALS;
GeomAnaTool_ExtractBOPFailure aTool (aList);
aTool.SetUseTimer(theUseTimer);
aTool.SetCheckGeometry(!theTopoOnly); // Either topo only or topo+geometry
aTool.SetRunParallel(theRunParallel);
aTool.SetExactCheck(theDoExact);
aTool.Perform();
// Check, if there are execution errors
const Handle(Message_Report) aReport = aTool.GetReport();
Standard_SStream anOS;
aReport->Dump(anOS);
if (!anOS.str().empty()) {
SetErrorCode(anOS.str().c_str());
if (aTool.HasFailureAlerts()) {
return false;
}
}
TopoDS_Shape aShapeRes = aTool.Result();
if (aShapeRes.IsNull()) {
return false;
}
// Create Partition object.
theResultShape = GetEngine()->AddObject(GEOM_PARTITION);
Handle(GEOM_Function) aFunction = theResultShape->AddFunction
(GEOMImpl_PartitionDriver::GetID(), PARTITION_GENERAL_FUSE);
// For creation information filling
GEOMImpl_IPartition aCI (aFunction);
aCI.SetShapes(aShapesSeq);
// Set General Fuse result right here
// (without driver execution, as we already have the result shape)
aFunction->SetValue(aShapeRes);
theErrors = aTool.ShapeErrors();
isValid = theErrors.size() == 0;
//Make a Python command
GEOM::TPythonDump aPD (aFunction);
aPD << "(isBOPFailure, " << theResultShape
<< ", anErrors) = geompy.ExtractBOPFailure([";
for (int i = 1; i <= aNbShapes; i++) {
aPD << Handle(GEOM_Object)::DownCast(theShapes->Value(i));
if (i < aNbShapes) aPD << ", ";
}
aPD << "], " << theUseTimer << ", " << theTopoOnly
<< ", " << theRunParallel << ", " << theDoExact << ")";
}
catch(Standard_Failure& aFail)
{
SetErrorCode(aFail.GetMessageString());
return false;
}
return isValid;
}
//=============================================================================
/*!
* CheckSelfIntersections
@ -1832,11 +1944,11 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast
// Launch the checker
aTool.Perform();
const BRepExtrema_MapOfIntegerPackedMapOfInteger& intersections = aTool.OverlapElements();
std::set<Standard_Integer> processed;
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator it(intersections); it.More(); it.Next()) {
Standard_Integer idxLeft = it.Key();
if (processed.count(idxLeft) > 0) continue; // already added
@ -1954,14 +2066,14 @@ bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1,
// 1. Launch the checker
aBSP.Perform();
// 2. Get sets of IDs of overlapped faces
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
{
const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key());
theIntersections1->Append(anIndices1.FindIndex(aS1));
}
for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
{
const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key());
@ -2330,7 +2442,7 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object)
for (int i = 1; i <= nbSolutions; i++) {
P1 = dst.PointOnShape1(i);
P2 = dst.PointOnShape2(i);
theDoubles->Append(P1.X());
theDoubles->Append(P1.Y());
theDoubles->Append(P1.Z());
@ -3504,161 +3616,6 @@ double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge
return aMaxDist;
}
//=======================================================================
//function : FillErrorsSub
//purpose : Fill the errors list of subshapes on shape.
//=======================================================================
void GEOMImpl_IMeasureOperations::FillErrorsSub
(const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
const TopAbs_ShapeEnum theSubType,
TopTools_DataMapOfIntegerListOfShape &theMapErrors) const
{
TopExp_Explorer anExp(theShape, theSubType);
TopTools_MapOfShape aMapSubShapes;
for (; anExp.More(); anExp.Next()) {
const TopoDS_Shape &aSubShape = anExp.Current();
if (aMapSubShapes.Add(aSubShape)) {
const Handle(BRepCheck_Result) &aRes = theAna.Result(aSubShape);
for (aRes->InitContextIterator();
aRes->MoreShapeInContext();
aRes->NextShapeInContext()) {
if (aRes->ContextualShape().IsSame(theShape)) {
BRepCheck_ListIteratorOfListOfStatus itl(aRes->StatusOnShape());
if (itl.Value() != BRepCheck_NoError) {
// Add all errors for theShape and its sub-shape.
for (;itl.More(); itl.Next()) {
const Standard_Integer aStat = (Standard_Integer)itl.Value();
if (!theMapErrors.IsBound(aStat)) {
TopTools_ListOfShape anEmpty;
theMapErrors.Bind(aStat, anEmpty);
}
TopTools_ListOfShape &theShapes = theMapErrors.ChangeFind(aStat);
theShapes.Append(aSubShape);
theShapes.Append(theShape);
}
}
}
break;
}
}
}
}
//=======================================================================
//function : FillErrors
//purpose : Fill the errors list.
//=======================================================================
void GEOMImpl_IMeasureOperations::FillErrors
(const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
TopTools_DataMapOfIntegerListOfShape &theMapErrors,
TopTools_MapOfShape &theMapShapes) const
{
if (theMapShapes.Add(theShape)) {
// Fill errors of child shapes.
for (TopoDS_Iterator iter(theShape); iter.More(); iter.Next()) {
FillErrors(theAna, iter.Value(), theMapErrors, theMapShapes);
}
// Fill errors of theShape.
const Handle(BRepCheck_Result) &aRes = theAna.Result(theShape);
if (!aRes.IsNull()) {
BRepCheck_ListIteratorOfListOfStatus itl(aRes->Status());
if (itl.Value() != BRepCheck_NoError) {
// Add all errors for theShape.
for (;itl.More(); itl.Next()) {
const Standard_Integer aStat = (Standard_Integer)itl.Value();
if (!theMapErrors.IsBound(aStat)) {
TopTools_ListOfShape anEmpty;
theMapErrors.Bind(aStat, anEmpty);
}
theMapErrors.ChangeFind(aStat).Append(theShape);
}
}
}
// Add errors of subshapes on theShape.
const TopAbs_ShapeEnum aType = theShape.ShapeType();
switch (aType) {
case TopAbs_EDGE:
FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
break;
case TopAbs_FACE:
FillErrorsSub(theAna, theShape, TopAbs_WIRE, theMapErrors);
FillErrorsSub(theAna, theShape, TopAbs_EDGE, theMapErrors);
FillErrorsSub(theAna, theShape, TopAbs_VERTEX, theMapErrors);
break;
case TopAbs_SOLID:
FillErrorsSub(theAna, theShape, TopAbs_SHELL, theMapErrors);
break;
default:
break;
}
}
}
//=======================================================================
//function : FillErrors
//purpose : Fill the errors list.
//=======================================================================
void GEOMImpl_IMeasureOperations::FillErrors
(const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
std::list<ShapeError> &theErrors) const
{
// Fill the errors map.
TopTools_DataMapOfIntegerListOfShape aMapErrors;
TopTools_MapOfShape aMapShapes;
FillErrors(theAna, theShape, aMapErrors, aMapShapes);
// Map sub-shapes and their indices
TopTools_IndexedMapOfShape anIndices;
TopExp::MapShapes(theShape, anIndices);
TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aMapIter(aMapErrors);
for (; aMapIter.More(); aMapIter.Next()) {
ShapeError anError;
anError.error = (BRepCheck_Status)aMapIter.Key();
TopTools_ListIteratorOfListOfShape aListIter(aMapIter.Value());
TopTools_MapOfShape aMapUnique;
for (; aListIter.More(); aListIter.Next()) {
const TopoDS_Shape &aShape = aListIter.Value();
if (aMapUnique.Add(aShape)) {
const Standard_Integer anIndex = anIndices.FindIndex(aShape);
anError.incriminated.push_back(anIndex);
}
}
if (!anError.incriminated.empty()) {
theErrors.push_back(anError);
}
}
}
//=======================================================================
//function : ShapeProximityCalculator
//purpose : returns an object to compute the proximity value

View File

@ -25,6 +25,8 @@
#include "GEOM_IOperations.hxx"
#include <GeomAnaTool_Tools.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepCheck_Status.hxx>
#include <TopoDS_Shape.hxx>
@ -149,30 +151,34 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations {
Standard_Real& EdgeMin, Standard_Real& EdgeMax,
Standard_Real& VertMin, Standard_Real& VertMax);
struct ShapeError {
BRepCheck_Status error;
std::list<int> incriminated;
};
Standard_EXPORT bool CheckShape (Handle(GEOM_Object) theShape,
const Standard_Boolean theIsCheckGeom,
std::list<ShapeError> &theErrors);
std::list<GeomAnaTool::ShapeError> &theErrors);
Standard_EXPORT TCollection_AsciiString PrintShapeErrors
(Handle(GEOM_Object) theShape,
const std::list<ShapeError> &theErrors);
const std::list<GeomAnaTool::ShapeError> &theErrors);
Standard_EXPORT bool ExtractBOPFailure
(const Handle(TColStd_HSequenceOfTransient)& theShapes,
const bool theUseTimer,
const bool theTopoOnly,
const bool theRunParallel,
const bool theDoExact,
Handle(GEOM_Object)& theResultShape,
std::list<GeomAnaTool::ShapeError>& theErrors);
Standard_EXPORT bool CheckSelfIntersections (Handle(GEOM_Object) theShape,
const SICheckLevel theCheckLevel,
Handle(TColStd_HSequenceOfInteger)& theIntersections);
Standard_EXPORT bool CheckSelfIntersectionsFast (Handle(GEOM_Object) theShape,
float deflection,
float deflection,
double tolerance,
Handle(TColStd_HSequenceOfInteger)& theIntersections);
Standard_EXPORT bool CheckBOPArguments (const Handle(GEOM_Object) &theShape);
Standard_EXPORT bool FastIntersect (Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2,
double tolerance, float deflection,
Handle(TColStd_HSequenceOfInteger)& theIntersections1,
@ -271,21 +277,6 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations {
private:
void FillErrorsSub
(const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
const TopAbs_ShapeEnum theSubType,
TopTools_DataMapOfIntegerListOfShape &theMapErrors) const;
void FillErrors
(const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
TopTools_DataMapOfIntegerListOfShape &theMapErrors,
TopTools_MapOfShape &theMapShapes) const;
void FillErrors (const BRepCheck_Analyzer &theAna,
const TopoDS_Shape &theShape,
std::list<ShapeError> &theErrors) const;
Standard_Real getSurfaceCurvatures (const Handle(Geom_Surface)& aSurf,
Standard_Real theUParam,
Standard_Real theVParam,

View File

@ -564,6 +564,9 @@ GetCreationInformation(std::string& theOperationName,
AddParam( theParams, "Object", aCI.GetShape() );
AddParam( theParams, "Plane", aCI.GetPlane() );
break;
case PARTITION_GENERAL_FUSE:
AddParam( theParams, "Objects", aCI.GetShapes() );
break;
default:
return false;
}

View File

@ -268,6 +268,7 @@
#define PARTITION_PARTITION 1
#define PARTITION_HALF 2
#define PARTITION_NO_SELF_INTERSECTIONS 3
#define PARTITION_GENERAL_FUSE 4
#define POLYLINE_POINTS 1
#define POLYLINE2D_PLN_COORDS 2

View File

@ -25,6 +25,7 @@ INCLUDE_DIRECTORIES(
${PTHREAD_INCLUDE_DIR}
${OpenCASCADE_INCLUDE_DIR}
${KERNEL_INCLUDE_DIRS}
${CommonGeomLib_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/GEOMImpl
${PROJECT_SOURCE_DIR}/src/GEOM
${PROJECT_SOURCE_DIR}/src/GEOMAlgo
@ -47,6 +48,7 @@ ENDIF(WIN32)
# libraries to link to
SET(_link_LIBRARIES
${CommonGeomLib_GeomAnaTool}
GEOMImpl
GEOMUtils
SalomeIDLGEOM

View File

@ -22,6 +22,7 @@
#include <Standard_Stream.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_HSequenceOfTransient.hxx>
#include "GEOM_IMeasureOperations_i.hh"
@ -42,7 +43,7 @@
*/
static void ConvertShapeError
(const GEOM::GEOM_IMeasureOperations::ShapeErrors &theErrorsFrom,
std::list<GEOMImpl_IMeasureOperations::ShapeError> &theErrorsTo)
std::list<GeomAnaTool::ShapeError> &theErrorsTo)
{
int aNbErr = theErrorsFrom.length();
int i = 0;
@ -51,7 +52,7 @@ static void ConvertShapeError
const GEOM::GEOM_IMeasureOperations::ShapeError anErr = theErrorsFrom[i];
const GEOM::GEOM_IMeasureOperations::ShapeErrorType aType = anErr.error;
const GEOM::ListOfLong anIncrims = anErr.incriminated;
GEOMImpl_IMeasureOperations::ShapeError anErrStruct;
GeomAnaTool::ShapeError anErrStruct;
switch (aType) {
case GEOM::GEOM_IMeasureOperations::InvalidPointOnCurve:
@ -176,7 +177,7 @@ static void ConvertShapeError
* \param theErrorsTo result errors.
*/
static void ConvertShapeError
(const std::list<GEOMImpl_IMeasureOperations::ShapeError> &theErrorsFrom,
(const std::list<GeomAnaTool::ShapeError> &theErrorsFrom,
GEOM::GEOM_IMeasureOperations::ShapeErrors_out &theErrorsTo)
{
const int aNbErr = theErrorsFrom.size();
@ -186,7 +187,7 @@ static void ConvertShapeError
anErrArray->length(aNbErr);
// fill the local CORBA array with values from lists
std::list<GEOMImpl_IMeasureOperations::ShapeError>::const_iterator
std::list<GeomAnaTool::ShapeError>::const_iterator
anIt = theErrorsFrom.begin();
int i = 0;
@ -644,7 +645,7 @@ CORBA::Boolean GEOM_IMeasureOperations_i::CheckShape
return 0;
}
std::list<GEOMImpl_IMeasureOperations::ShapeError> anErrList;
std::list<GeomAnaTool::ShapeError> anErrList;
bool isOk = GetOperations()->CheckShape(aShape, false, anErrList);
ConvertShapeError(anErrList, theErrors);
@ -672,7 +673,7 @@ CORBA::Boolean GEOM_IMeasureOperations_i::CheckShapeWithGeometry
return 0;
}
std::list<GEOMImpl_IMeasureOperations::ShapeError> anErrList;
std::list<GeomAnaTool::ShapeError> anErrList;
bool isOk = GetOperations()->CheckShape(aShape, true, anErrList);
ConvertShapeError(anErrList, theErrors);
@ -699,7 +700,7 @@ char* GEOM_IMeasureOperations_i::PrintShapeErrors
}
// Convert the errors sequence
std::list<GEOMImpl_IMeasureOperations::ShapeError> anErrList;
std::list<GeomAnaTool::ShapeError> anErrList;
ConvertShapeError(theErrors, anErrList);
@ -709,6 +710,66 @@ 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 theRunParallel,
CORBA::Boolean theDoExact,
GEOM::GEOM_Object_out theResultShape,
GEOM::GEOM_IMeasureOperations::ShapeErrors_out theErrors)
{
GEOM::GEOM_Object_var aNullRes;
theResultShape = aNullRes._retn();
// Set the not done flag
theErrors = new GEOM::GEOM_IMeasureOperations::ShapeErrors;
GetOperations()->SetNotDone();
// Check for existing shapes
int aNbShapes = theShapes.length();
if (!aNbShapes)
{
return 0;
}
// Create the sequence of GEOM objects for the failure shapes
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
Handle(::GEOM_Object) aResultShape;
std::list<GeomAnaTool::ShapeError> anErrList;
bool isOk = GetOperations()->ExtractBOPFailure
(aSeqShapes, theUseTimer, theTopoOnly, theRunParallel,
theDoExact, aResultShape, anErrList);
if (!aResultShape.IsNull()) {
theResultShape = GetObject(aResultShape);
}
ConvertShapeError(anErrList, theErrors);
return isOk;
}
//=============================================================================
/*!
* CheckSelfIntersections

View File

@ -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 theRunParallel,
CORBA::Boolean theDoExact,
GEOM::GEOM_Object_out theResultShape,
GEOM::GEOM_IMeasureOperations::ShapeErrors_out theErrors);
CORBA::Boolean CheckSelfIntersections (GEOM::GEOM_Object_ptr theShape,
CORBA::Long theCheckLevel,
GEOM::ListOfLong_out theIntersections);

View File

@ -3113,7 +3113,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
anObj.SetParameters(Parameters)
self._autoPublish(anObj, theName, "cylinder")
return anObj
## Create a portion of cylinder with given base point, axis, radius, height and angle.
# @param thePnt Central point of cylinder base.
# @param theAxis Cylinder axis.
@ -3196,7 +3196,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
anObj.SetParameters(Parameters)
self._autoPublish(anObj, theName, "cylinder")
return anObj
## Create a portion of cylinder with given radius, height and angle at
# the origin of coordinate system. Axis of the cylinder
# will be collinear to the OZ axis of the coordinate system.
@ -3999,7 +3999,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created pipe if
# @return New GEOM.GEOM_Object, containing the created pipe if
# \a IsGenerateGroups is not set. Otherwise it returns a
# list of GEOM.GEOM_Object. Its first element is the created pipe, the
# remaining ones are created groups.
@ -4039,7 +4039,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created pipe if
New GEOM.GEOM_Object, containing the created pipe if
IsGenerateGroups is not set. Otherwise it returns a
list of GEOM.GEOM_Object. Its first element is the created pipe, the
remaining ones are created groups.
@ -4076,7 +4076,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created pipe if
# @return New GEOM.GEOM_Object, containing the created pipe if
# \a IsGenerateGroups is not set. Otherwise it returns new
# GEOM.ListOfGO. Its first element is the created pipe, the
# remaining ones are created groups.
@ -4112,7 +4112,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created pipe if
New GEOM.GEOM_Object, containing the created pipe if
IsGenerateGroups is not set. Otherwise it returns new
GEOM.ListOfGO. Its first element is the created pipe, the
remaining ones are created groups.
@ -4197,7 +4197,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created solids if
# @return New GEOM.GEOM_Object, containing the created solids if
# \a IsGenerateGroups is not set. Otherwise it returns new
# GEOM.ListOfGO. Its first element is the created solids, the
# remaining ones are created groups.
@ -4242,7 +4242,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created solids if
New GEOM.GEOM_Object, containing the created solids if
IsGenerateGroups is not set. Otherwise it returns new
GEOM.ListOfGO. Its first element is the created solids, the
remaining ones are created groups.
@ -4320,7 +4320,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created solids if
# @return New GEOM.GEOM_Object, containing the created solids if
# \a IsGenerateGroups is not set. Otherwise it returns new
# GEOM.ListOfGO. Its first element is the created solids, the
# remaining ones are created groups.
@ -4345,7 +4345,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created solids if
New GEOM.GEOM_Object, containing the created solids if
IsGenerateGroups is not set. Otherwise it returns new
GEOM.ListOfGO. Its first element is the created solids, the
remaining ones are created groups.
@ -4378,7 +4378,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return New GEOM.GEOM_Object, containing the created pipe if
# @return New GEOM.GEOM_Object, containing the created pipe if
# \a IsGenerateGroups is not set. Otherwise it returns new
# GEOM.ListOfGO. Its first element is the created pipe, the
# remaining ones are created groups.
@ -4408,7 +4408,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
publication is switched on, default value is used for result name.
Returns:
New GEOM.GEOM_Object, containing the created pipe if
New GEOM.GEOM_Object, containing the created pipe if
IsGenerateGroups is not set. Otherwise it returns new
GEOM.ListOfGO. Its first element is the created pipe, the
remaining ones are created groups.
@ -4433,7 +4433,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# @param theThickness Thickness of the resulting solid
# @param theFacesIDs the list of face IDs to be removed from the
# result. It is ignored if \a theShape is a face or a shell.
# It is empty by default.
# It is empty by default.
# @param theInside If true the thickness is applied towards inside
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
@ -4456,7 +4456,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
theThickness Thickness of the resulting solid
theFacesIDs the list of face IDs to be removed from the
result. It is ignored if theShape is a face or a
shell. It is empty by default.
shell. It is empty by default.
theInside If true the thickness is applied towards inside
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
@ -4483,7 +4483,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# @param theThickness Thickness of the resulting solid
# @param theFacesIDs the list of face IDs to be removed from the
# result. It is ignored if \a theShape is a face or a shell.
# It is empty by default.
# It is empty by default.
# @param theInside If true the thickness is applied towards inside
#
# @return The modified shape
@ -4503,7 +4503,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
theThickness Thickness of the resulting solid
theFacesIDs the list of face IDs to be removed from the
result. It is ignored if \a theShape is a face or
a shell. It is empty by default.
a shell. It is empty by default.
theInside If true the thickness is applied towards inside
Returns:
@ -4960,7 +4960,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
RaiseIfFailed("MakeFaceFromSurface", self.ShapesOp)
self._autoPublish(anObj, theName, "face")
return anObj
## Create a non-planar face from a list of closed edges and a list of vertices.
# @param theEdges list of Edges(must be closed but not nesessarily belong to the same plane).
# @param theVertices list of vertices through which the result face must pass.
@ -4993,7 +4993,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
RaiseIfFailed("MakeWrappedFace", self.ShapesOp)
self._autoPublish(anObj, theName, "face")
return anObj
## Create a face from a set of edges with the given constraints.
# @param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples):
# - edges should form a closed wire;
@ -5002,9 +5002,9 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
#
# @return New GEOM.GEOM_Object, containing the created face.
#
#
# @ref tui_creation_face "Example"
@ManageTransactions("ShapesOp")
def MakeFaceWithConstraints(self, theConstraints, theName=None):
@ -5123,7 +5123,7 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
RaiseIfFailed("MakeCompound", self.ShapesOp)
self._autoPublish(anObj, theName, "compound")
return anObj
## Create a solid (or solids) from the set of faces and/or shells.
# @param theFacesOrShells List of faces and/or shells.
# @param isIntersect If TRUE, forces performing intersections
@ -11982,6 +11982,56 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
"""
return self.MeasuOp.CheckBOPArguments(theShape)
## Performs general fuse BOP on the given list of shapes
# and extracts CheckShape information from its invalid result.
# @param theShapes List of shapes for the BOP.
# @param theTimer If True, the execution time of the operation is measured.
# @param theTopo If True, only the topological entities will be checked.
# @param theParallel If True, the operation will be executed in parallel.
# @param theExact If True, an exact check will be performed.
# @param theVerbose If True, prints execution errors and resulting shape errors.
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
# @return (isValid, shapeResult, listOfErrors), where
# isValid - a boolean value (whether result shape is valid or not),
# shapeResult - the result shape itself as GEOM::Object,
# listOfErrors - the list of GEOM.GEOM_IMeasureOperations.ShapeError.
def ExtractBOPFailure(self, theShapes, theTimer=False, theTopo=False, theParallel=False, theExact=False, theVerbose=False, theName=None):
"""
Performs general fuse BOP on the given list of shapes
and extracts CheckShape information from its invalid result.
Parameters:
theShapes List of shapes for the BOP.
theTimer If True, the time of the operation is measured.
theTopo If True, only the topological entities will be checked.
theParallel If True, the operation will be executed in parallel.
theExact If True, an exact check will be performed.
theVerbose If True, prints execution errors and resulting shape errors.
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
publication is switched on, default value is used for result name.
Returns:
(isValid, shapeResult, listOfErrors), where
isValid - a boolean value (whether result shape is valid or not),
shapeResult - the result shape itself as GEOM::Object,
listOfErrors - the list of GEOM.GEOM_IMeasureOperations.ShapeError.
"""
(IsValid, ShapeRes, ShapeErrors) = self.MeasuOp.ExtractBOPFailure(theShapes, theTimer, theTopo, theParallel, theExact)
if theVerbose:
if not self.MeasuOp.IsDone():
print("== ExtractBOPFailure execution trace:")
print(self.MeasuOp.GetErrorCode())
if not IsValid:
print("== ExtractBOPFailure result errors:")
self.PrintShapeErrors(ShapeRes, ShapeErrors)
if ShapeRes:
self._autoPublish(ShapeRes, theName, "InvalidBOPResult")
return (IsValid, ShapeRes, ShapeErrors)
## Detect intersections of the given shapes with algorithm based on mesh intersections.
# @param theShape1 First source object
# @param theShape2 Second source object

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -26,6 +26,7 @@ ENDIF()
# additional include directories
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
${CommonGeomLib_INCLUDE_DIRS}
${KERNEL_INCLUDE_DIRS}
${PROJECT_BINARY_DIR}/idl
${PROJECT_SOURCE_DIR}/src/GEOMAlgo

View File

@ -0,0 +1,388 @@
DBRep_DrawableShape
CASCADE Topology V3, (c) Open Cascade
Locations 2
1
1 0 0 -7.567891
0 1 0 -4.341567
0 0 1 -6.123456
2 1 -1 0
Curve2ds 20
1 5.2296342291324773 3.3322056701893321 -0.019393351731739859 -0.99981193126938084
1 4.1177697329478473 -7.9576022773085979 0.74914523473738692 0.66240577991912586
2 7.6778616423679917 5.5784416873630649 1.0327963672288199e-28 1 -1 1.0327963672288199e-28 13.996383126259545
1 1.2238101114815878 -6.1633524984935972 -0.18530824692372716 -0.98268044328868942
1 1.2235485004159372 -2.2110670843958085 6.6192351428950508e-05 -0.99999999780928628
1 -0.76442260860377154 0.24528750719338177 0.62910141048581703 -0.77732323735030318
1 -3.7293599477436921 -2.8998812708177271 0.68595070867481067 0.72764800918337236
2 8.2082756373678425 6.9866174666722882 1 -5.2064482382916161e-32 5.2064482382916161e-32 1 15.500000020945576
1 -5.5702632964129428 -0.1128096580751663 0.62013158110931121 0.78449781523651529
1 -1.2787866923231981 5.3161253012195147 0.66335395303032052 -0.74830577506728313
1 6.2831853071795862 -27.994292694933499 -1 0
1 2.2305029134341128 -29.744292694933499 0 1
1 1.1682335865018412e-13 -26.364292694933447 1 0
1 2.2737127428085482 -25.744292694933499 0 -1
1 1.1577157318429796e-13 -25.744292694933449 1 0
1 2.2305029134341128 -25.744292694933399 0 1
1 6.2831853071795862 -24.494292694933499 -1 0
7 0 0 5 6 2 2.66538798008808 -22.744292694933499 2.6653879800880054 -23.468292694933499 2.6653879800879281 -24.192292694933485 2.6653879800878677 -24.916292694933531 2.6653879800877802 -25.6402926949335 2.6653879800877056 -26.3642926949335
0 6 3.6200000000000001 6
1 -1.5707963267948966 -26.364292694933503 1 0
1 2.6969123268332003 -29.744292694933499 0 1
Curves 20
1 3.6643099095142699 2.9989666286603298 7.3799999999999901 0.99981193126938084 0.019393351731739859 0
1 14.9541178570122 4.1108311248449603 7.3799999999999901 -0.66240577991912586 -0.74914523473738692 0
2 1.4180738923405372 0.55073921542481585 7.3800000000004342 -2.974710134687989e-14 -1.1637659715336122e-14 -1 -1 0 2.974710134687989e-14 -3.46186642992605e-28 1 -1.1637659715336122e-14 13.996383126259545
1 13.159868078197199 7.0047907463112198 7.3799999999999901 0.98268044328868942 0.18530824692372716 0
1 9.2075826640994105 7.0050523573768704 7.3799999999999901 0.99999999780928628 -6.6192351428950508e-05 0
1 6.7512280725102203 8.9930234663965791 7.3799999999999901 0.77732323735030318 -0.62910141048581703 0
1 9.8963968505213291 11.9579608055365 7.3799999999999599 -0.72764800918337236 -0.68595070867481067 6.9864494891450316e-15
2 0.0098981130313138266 0.020325220424965096 7.3800000000000123 -4.8764518640683504e-16 -3.985833116056589e-15 -1 0 -1 3.985833116056589e-15 -1 1.9436723328659514e-30 4.8764518640683504e-16 15.500000020945576
1 7.1093252377787683 13.79886415420575 7.3799999999999537 -0.78449781523651529 -0.62013158110931121 2.951923868206801e-15
1 1.6803902784840878 9.5073875501160057 7.3799999999999741 0.74830577506728313 -0.66335395303032052 1.65532199479636e-15
2 0.048629684365062174 0.040085253947511945 5.75 -1.8938307431288352e-32 -1.4228181456116284e-32 1 -1 0 -1.8938307431288352e-32 2.6945767460408616e-64 -1 -1.4228181456116284e-32 15.447113622753015
1 9.5159344006809405 12.245963374044599 4 0 0 1
2 0.048629684364520642 0.040085253947925281 7.3800000000000505 -1.1682335865018412e-13 9.4687192060776203e-14 -1 -1 0 1.1682335865018412e-13 1.1061675797694924e-26 1 9.4687192060776203e-14 15.447113622753017
1 10.0343474285764 11.8256170793334 8 0 0 -1
2 0.048629684364520642 0.040085253947925281 8.0000000000000497 -1.1577157318429796e-13 9.3871390575314678e-14 -1 -1 0 1.1577157318429796e-13 1.0867638563901861e-26 1 9.3871390575314678e-14 15.447113622753017
1 9.5159344006809405 12.245963374044599 8.0000000000000995 0 0 1
2 0.048629684365062174 0.040085253947511945 9.25 -1.8938307431288352e-32 -1.4228181456116284e-32 1 -1 0 -1.8938307431288352e-32 2.6945767460408616e-64 -1 -1.4228181456116284e-32 15.447113622753015
1 13.7771149464134 7.1211876881706102 11 -7.183940367077256e-13 1.4252564751486263e-12 -1
2 0.048629684365860015 0.040085253945864707 7.3799999999999955 -8.9410861073054036e-15 1.7961675054224776e-14 -1 0 -1 -1.7961675054224776e-14 -1 -1.6059688329126317e-28 8.9410861073054036e-15 15.447113622753015
1 13.9934840908598 6.6849595835271503 4 0 0 1
Polygon3D 0
PolygonOnTriangulations 0
Surfaces 2
1 6.9965155797036021 8.2286008577928076 7.3799999999999759 1.0131042642695293e-16 -3.4719227099992637e-15 -1 0 -1 3.4719227099992637e-15 -1 -3.5174197027144744e-31 -1.0131042642695293e-16
2 0.048629684365062174 0.040085253947511945 33.744292694933499 -1.8938307431288352e-32 -1.4228181456116284e-32 1 -1 0 -1.8938307431288352e-32 -2.6945767460408616e-64 1 1.4228181456116284e-32 15.447113622753015
Triangulations 0
TShapes 45
Ve
0.00100000000000355
1.33968696229361 -1.24089670248843 1.25654399999999
0 0
0101101
*
Ve
0.001
6.582955015073 -1.13919303363718 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 1 0 5.2442543330348 10.4885086660696
2 1 1 0 5.2442543330348 10.4885086660696
0
0101000
+45 2 -44 2 *
Ve
0.001
7.3862268570122 -0.23073587515504 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 2 0 0 1.21265826218677
2 2 1 0 0 1.21265826218677
0
0101000
+42 2 -44 2 *
Ve
0.001
6.2085640030866 2.77949617536757 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 3 0 2.65294738721352 2.88440884989702
2 3 1 0 2.65294738721352 2.88440884989702
0
0101000
+40 2 -42 2 *
Ve
0.001
5.5919770781972 2.66322374631122 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 4 0 0 0.627454152670321
2 4 1 0 0 0.627454152670321
0
0101000
+38 2 -40 2 *
Ve
0.001
1.63969166409941 2.66348535737687 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 5 0 0 3.95228542275611
2 5 1 0 0 3.95228542275611
0
0101000
+36 2 -38 2 *
Ve
0.001
-0.81666292748978 4.65145646639658 1.25654399999999
0 0
0101101
*
Ed
0.001 1 1 0
1 6 0 0 3.16001693190374
2 6 1 0 0 3.16001693190374
0
0101000
+34 2 -36 2 *
Ve
0.001
2.32850585052133 7.6163938055365 1.25654399999996
0 0
0101101
*
Ed
0.001 1 1 0
1 7 0 0 4.32237666882492
2 7 1 0 0 4.32237666882492
0
0101000
+32 2 -34 2 *
Ve
0.00100000000000266
-0.45856576222123 9.4572971542058 1.25654399999995
0 0
0101101
*
Ed
0.001 1 1 0
1 8 0 3.61736770330259 3.83328128895929
2 8 1 0 3.61736770330259 3.83328128895929
0
0101000
+30 2 -32 2 *
Ve
0.00100000000000355
-5.88750072151591 5.16582055011601 1.25654399999997
0 0
0101101
*
Ed
0.00100000000000266 1 1 0
1 9 0 0 6.92026778641561
2 9 1 0 0 6.92026778641561
0
0101000
+30 2 -28 2 *
Ed
0.00100000000000355 1 1 0
1 10 0 0 9.65806749675251
2 10 1 0 0 9.65806749675251
0
0101000
+28 2 -45 2 *
Wi
0101100
-43 0 +41 0 +39 0 +37 0 +35 0 +33 0 +31 0 +29 0 -27 0 -26 0
*
Fa
0 0.001 1 0
0111000
+25 0 *
Ve
0.001100100001
6.4255930908598 2.34339258352715 -0.373456
0 0
0101101
*
Ve
0.001100100001
1.94804340068094 7.9043963740446 -0.373456
0 0
0101101
*
Ed
0.0011 1 1 0
1 11 0 3.58627298034639 4.05268239374548
2 11 2 0 3.58627298034639 4.05268239374548
0
0101000
+23 2 -22 2 *
Ve
0.0011
1.94804340068094 7.9043963740446 1.2565440000001
0 0
0101101
*
Ed
0.0011 1 1 0
1 12 0 1.75 3.3800000000001
2 12 2 0 1.75 3.3800000000001
0
0101000
+22 2 -20 2 *
Ve
0.0011
2.4664564285764 7.4840500793334 1.256544
0 0
0101101
*
Ed
0.0011 1 1 0
1 13 0 2.23050291343416 2.27371274280859
2 13 2 0 2.23050291343416 2.27371274280859
0
0101000
+20 2 -18 2 *
Ve
0.0011
2.4664564285764 7.4840500793334 1.876544
0 0
0101101
*
Ed
0.0011 1 1 0
1 14 0 0 0.62
2 14 2 0 0 0.62
0
0101000
+16 2 -18 2 *
Ve
0.0011
1.94804340068094 7.9043963740446 1.8765440000001
0 0
0101101
*
Ed
0.0011 1 1 0
1 15 0 2.23050291343416 2.27371274280859
2 15 2 0 2.23050291343416 2.27371274280859
0
0101000
+14 2 -16 2 *
Ve
0.001100100001
1.94804340068094 7.9043963740446 3.126544
0 0
0101101
*
Ed
0.0011 1 1 0
1 16 0 0 1.2499999999999
2 16 2 0 0 1.2499999999999
0
0101000
+14 2 -12 2 *
Ve
0.001100100001
6.2092239464121 2.7796206881731 3.126544
0 0
0101101
*
Ed
0.0011 1 1 0
1 17 0 3.61779732709169 4.05268239374548
2 17 2 0 3.61779732709169 4.05268239374548
0
0101000
+10 2 -12 2 *
Ve
0.0011
6.2092239464108 2.77962068817577 1.256544
0 0
0101101
*
Ed
0.0011 1 1 0
1 18 0 1.75 3.62
2 18 2 0 1.75 3.62
0
0101000
+10 2 -8 2 *
Ve
0.0011
6.4255930908598 2.34339258352715 1.25654399999999
0 0
0101101
*
Ed
0.0011 1 1 0
1 19 0 4.23618430688248 4.26770865362798
2 19 2 0 4.23618430688248 4.26770865362798
0
0101000
+8 2 -6 2 *
Ed
0.0011 1 1 0
1 20 0 1.75 3.37999999999999
2 20 2 0 1.75 3.37999999999999
0
0101000
+23 2 -6 2 *
Wi
0101100
-21 0 -19 0 -17 0 +15 0 +13 0 -11 0 +9 0 -7 0 -5 0 +4 0
*
Fa
0 0.0011 2 0
0111000
+3 0 *
Co
1100000
+24 0 -2 0 *
+1 1
0

85
test/test_ExtractBOPFailure.py Executable file
View File

@ -0,0 +1,85 @@
# Copyright (C) 2024 CEA, EDF
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
# Test ExtractBOPFailure method
from inspect import getfile
from os.path import abspath, dirname, join
import salome
from salome.geom import geomBuilder
geompy = geomBuilder.New()
data_dir = abspath(join(dirname(getfile(lambda: None)), 'data'))
### Case 1: Invalid face with (3) intersecting wires
Shapes_1 = geompy.ImportBREP(join(data_dir, "ExtractBOPFailure_compound1.brep"))
geompy.addToStudy( Shapes_1, 'CompoundPostIdealisation' )
try :
Partition_1 = geompy.MakePartition([Shapes_1],[])
except :
print("EXCEPTION: Partition problem")
print("Case 1: Invalid face with (3) intersecting wires")
(IsValid, GFRes, ShapeErrors) = geompy.ExtractBOPFailure([Shapes_1], theTimer=True, theVerbose=True)
assert GFRes is not None, "Resulting shape expected in Case #1"
geompy.addToStudy( GFRes, 'GFRes_Case_1' )
assert not IsValid, "IsValid == False expected in Case #1"
assert len(ShapeErrors) == 1, "One error expected"
list_ids = ShapeErrors[0].incriminated
assert len(list_ids) == 1, "One incriminated shape expected"
[Face_1] = geompy.SubShapes(GFRes, list_ids)
geompy.addToStudyInFather( GFRes, Face_1, 'Bad face' )
list_wires = geompy.ExtractShapes(Face_1, geompy.ShapeType["WIRE"], True, "Wire")
assert len(list_wires) == 3, "Three wires expected"
### Case 2: Empty list of input shapes
print("Case 2: Empty list of input shapes")
(IsValid, GFRes, ShapeErrors) = geompy.ExtractBOPFailure([], theVerbose=True)
assert GFRes is None, "General Fuse result is NOT expected on empty list of shapes"
assert not IsValid, "IsValid == False expected on empty list of shapes"
assert len(ShapeErrors) == 0, "ExtractBOPFailure should report no errors on empty list of shapes"
### Case 3: One shape in list, and it is not a COMPOUND
print("Case 3: One shape in list, and it is not a COMPOUND")
(IsValid, GFRes, ShapeErrors) = geompy.ExtractBOPFailure([geompy.MakeBoxDXDYDZ(10,10,10)], theVerbose=True)
assert GFRes is None, "General Fuse result is NOT expected"
assert not IsValid, "IsValid == False expected"
assert len(ShapeErrors) == 0, "ExtractBOPFailure should report no errors here"
### Case 4: Unusual type Case (two orthogonal faces, Partition OK)
print("Case 4: Unusual type Case (two orthogonal faces, Partition OK)")
origin = geompy.MakeVertex(0,0,0)
oX = geompy.MakeVectorDXDYDZ(1,0,0)
YOZ = geompy.MakePlane(origin, oX, 5)
oY = geompy.MakeVectorDXDYDZ(0,1,0)
XOZ = geompy.MakePlane(origin, oY, 5)
(IsValid, GFRes, ShapeErrors) = geompy.ExtractBOPFailure([YOZ, XOZ], theVerbose=True)
assert GFRes is not None, "General Fuse result is expected"
geompy.addToStudy( GFRes, 'GFRes_Case_4' )
assert IsValid, "Valid result is expected"
assert len(ShapeErrors) == 0, "ExtractBOPFailure should report no errors here"
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

View File

@ -21,7 +21,8 @@ SET(ALL_TESTS
test_perf_01.py
test_patch_face_01.py
test_set_autocolor.py
)
test_ExtractBOPFailure.py
)
IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.3")
LIST(APPEND ALL_TESTS