diff --git a/doc/salome/examples/shape_proximity.py b/doc/salome/examples/shape_proximity.py
new file mode 100644
index 000000000..997730e93
--- /dev/null
+++ b/doc/salome/examples/shape_proximity.py
@@ -0,0 +1,39 @@
+# Shape Proximity
+
+import salome
+salome.salome_init_without_session()
+import GEOM
+from salome.geom import geomBuilder
+geompy = geomBuilder.New()
+
+# create conical and planar faces
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+Cone_1 = geompy.MakeConeR1R2H(100, 0, 300)
+Cone_1_face_3 = geompy.GetSubShape(Cone_1, [3])
+Cone_1_wire_4 = geompy.GetSubShape(Cone_1, [4])
+Face_1 = geompy.MakeFaceFromSurface(Cone_1_face_3, Cone_1_wire_4)
+Face_1_edge_5 = geompy.GetSubShape(Face_1, [5])
+Face_2 = geompy.MakeFaceObjHW(Face_1_edge_5, 200, 200)
+geompy.Rotate(Face_2, OY, 90*math.pi/180.0)
+Face_2_vertex_7 = geompy.GetSubShape(Face_2, [7])
+Translation_1 = geompy.MakeTranslationTwoPoints(Face_2, Face_2_vertex_7, O)
+
+shape1 = Face_1
+shape2 = Translation_1
+
+# perform proximity calculation with the default parameters
+p1 = geompy.ShapeProximity()
+proximity1 = p1.proximity(shape1, shape2)
+print("Proximity with default parameters: ", proximity1)
+
+# perform proximity calculation with custom parameters
+p2 = geompy.ShapeProximity()
+p2.setShapes(shape1, shape2)
+p2.setSampling(shape1, 100) # number of sample points for the first shape
+p2.setSampling(shape2, 40) # number of sample points for the second shape
+proximity2_coarse = p2.coarseProximity()
+proximity2_fine = p2.preciseProximity()
+print("Proximity with custom parameters: coarse = ", proximity2_coarse, "; precise = ", proximity2_fine)
diff --git a/doc/salome/examples/tests.set b/doc/salome/examples/tests.set
index 327d64070..c2c8eb81e 100644
--- a/doc/salome/examples/tests.set
+++ b/doc/salome/examples/tests.set
@@ -135,4 +135,5 @@ SET(GOOD_TESTS
working_with_groups_ex06.py
GEOM_Field.py
check_self_intersections_fast.py # OCC > 6.9.0
+ shape_proximity.py
)
diff --git a/doc/salome/gui/GEOM/input/shape_proximity.doc b/doc/salome/gui/GEOM/input/shape_proximity.doc
new file mode 100644
index 000000000..5c22223f9
--- /dev/null
+++ b/doc/salome/gui/GEOM/input/shape_proximity.doc
@@ -0,0 +1,31 @@
+/*!
+
+\page shape_proximity_page Shape Proximity
+
+The Shape Proximity operation calculates maximal of all possible distances between two shapes.
+
+This is just a TUI functionality. The provided class
+
+geompy.ShapeProximity()
+
+has an interface to compute proximity value with default parameters
+
+p = geompy.ShapeProximity()
+value = p.proximity(shape1, shape2)
+
+
+Moreover, it also provides the functionality to customize the calculation.
+For example, compute coarse proximity value basing on the number of sampling points for each shape,
+or compute the precise value as a refining operation after the coarse value calculation.
+
+p = geompy.ShapeProximity()
+p.setShapes(shape1, shape2) # customize calculator with input shapes
+p.setSampling(shape1, 100) # assign number of sample points for the first shape
+p.setSampling(shape2, 25) # assign number of sample points for the second shape
+coarse_proximity = p.coarseProximity() # rough proximity value basing on the shape sampling and tessellation
+fine_proximity = p.preciseProximity() # more precise proximity value using exact shapes
+
+
+See also a \ref tui_shape_proximity_page "TUI example".
+
+*/
diff --git a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc
index 3966c9c0f..a4e7f5c9d 100644
--- a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc
+++ b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc
@@ -22,6 +22,7 @@
\subpage tui_check_self_intersections_fast_page
\subpage tui_fast_intersection_page
\subpage tui_check_conformity_page
+\subpage tui_shape_proximity_page
*/
diff --git a/doc/salome/gui/GEOM/input/tui_shape_proximity.doc b/doc/salome/gui/GEOM/input/tui_shape_proximity.doc
new file mode 100644
index 000000000..34efab45d
--- /dev/null
+++ b/doc/salome/gui/GEOM/input/tui_shape_proximity.doc
@@ -0,0 +1,6 @@
+/*!
+
+\page tui_shape_proximity_page Compute Proximity between Shapes
+\tui_script{shape_proximity.py}
+
+*/
diff --git a/doc/salome/gui/GEOM/input/using_measurement_tools.doc b/doc/salome/gui/GEOM/input/using_measurement_tools.doc
index 11803eec2..c30850fd3 100644
--- a/doc/salome/gui/GEOM/input/using_measurement_tools.doc
+++ b/doc/salome/gui/GEOM/input/using_measurement_tools.doc
@@ -21,6 +21,7 @@
\subpage whatis_page "WhatIs"
\subpage inspect_object_operation_page "Inspect Object"
\subpage shape_statistics_operation_page "Shape Statistics"
+\subpage shape_proximity_page "Shapes Proximity"
\n To check their integrity:
diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl
index 89a1e7779..d33bc140d 100644
--- a/idl/GEOM_Gen.idl
+++ b/idl/GEOM_Gen.idl
@@ -4833,6 +4833,38 @@ module GEOM
* \param theShape Shape for update.
*/
double UpdateTolerance(in GEOM_Object theShape);
+
+ /*!
+ * \brief Get the calculator for the proximity value between the given shapes.
+ * \param theShape1,theShape2 Shapes to find proximity.
+ * \return The calculator object.
+ */
+ GEOM_Object ShapeProximityCalculator(in GEOM_Object theShape1, in GEOM_Object theShape2);
+
+ /*!
+ * \brief Set number sample points to compute the coarse proximity.
+ * \param theCalculator Proximity calculator.
+ * \param theShape Shape to be samples.
+ * \param theNbSamples Number of samples points.
+ */
+ void SetShapeSampling(in GEOM_Object theCalculator,
+ in GEOM_Object theShape,
+ in long theNbSamples);
+
+ /*!
+ * \brief Compute coarse value of the proximity basing on the polygonal representation of shapes.
+ * \param theCalculator Proximity calculator.
+ * \return Proximity value.
+ */
+ double GetCoarseProximity(in GEOM_Object theCalculator);
+
+ /*!
+ * \brief Compute precise value of the proximity basing on the exact shapes.
+ * \param theCalculator Proximity calculator.
+ * \return Proximity value.
+ */
+ double GetPreciseProximity(in GEOM_Object theCalculator);
+
};
// # GEOM_IGroupOperations:
diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt
index 6dbbae81e..f79a186a5 100644
--- a/src/GEOMImpl/CMakeLists.txt
+++ b/src/GEOMImpl/CMakeLists.txt
@@ -95,6 +95,7 @@ SET(GEOMImpl_HEADERS
GEOMImpl_ILine.hxx
GEOMImpl_IPatchFace.hxx
GEOMImpl_IPlane.hxx
+ GEOMImpl_IProximity.hxx
GEOMImpl_IMarker.hxx
GEOMImpl_ITranslate.hxx
GEOMImpl_IMirror.hxx
@@ -182,6 +183,7 @@ SET(GEOMImpl_HEADERS
GEOMImpl_FillingDriver.hxx
GEOMImpl_GlueDriver.hxx
GEOMImpl_PatchFaceDriver.hxx
+ GEOMImpl_ShapeProximityDriver.hxx
GEOMImpl_Types.hxx
GEOM_GEOMImpl.hxx
GEOMImpl_ICanonicalRecognition.hxx
@@ -261,6 +263,7 @@ SET(GEOMImpl_SOURCES
GEOMImpl_FillingDriver.cxx
GEOMImpl_GlueDriver.cxx
GEOMImpl_PatchFaceDriver.cxx
+ GEOMImpl_ShapeProximityDriver.cxx
GEOMImpl_FieldDriver.cxx
GEOMImpl_ICanonicalRecognition.cxx
)
diff --git a/src/GEOMImpl/GEOMImpl_Gen.cxx b/src/GEOMImpl/GEOMImpl_Gen.cxx
index 7df117c33..e1d7d3a28 100644
--- a/src/GEOMImpl/GEOMImpl_Gen.cxx
+++ b/src/GEOMImpl/GEOMImpl_Gen.cxx
@@ -84,6 +84,7 @@
#include
#include
#include
+#include
//=============================================================================
/*!
@@ -165,6 +166,7 @@ GEOMImpl_Gen::GEOMImpl_Gen()
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_MeasureDriver::GetID(), new GEOMImpl_MeasureDriver());
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PatchFaceDriver::GetID(), new GEOMImpl_PatchFaceDriver());
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ConformityDriver::GetID(), new GEOMImpl_ConformityDriver());
+ TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ShapeProximityDriver::GetID(), new GEOMImpl_ShapeProximityDriver());
// Field
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FieldDriver::GetID(), new GEOMImpl_FieldDriver());
diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
index 1c8c7add3..9c3f19753 100644
--- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
+++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
@@ -25,7 +25,9 @@
#include
#include
+#include
#include
+#include
#include
@@ -3278,3 +3280,193 @@ void GEOMImpl_IMeasureOperations::FillErrors
}
}
}
+
+//=======================================================================
+//function : ShapeProximityCalculator
+//purpose : returns an object to compute the proximity value
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator(
+ Handle(GEOM_Object) theShape1,
+ Handle(GEOM_Object) theShape2)
+{
+ SetErrorCode(KO);
+
+ if (theShape1.IsNull() || theShape2.IsNull())
+ return NULL;
+
+ Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY);
+ if (aProximityCalc.IsNull())
+ return NULL;
+
+ Handle(GEOM_Function) aProximityFuncCoarse =
+ aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE);
+ //Check if the function is set correctly
+ if (aProximityFuncCoarse.IsNull() ||
+ aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
+ return NULL;
+
+ GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
+ Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction();
+ Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
+ if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
+ return NULL;
+
+ aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
+
+ // Perform
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ if (!GetSolver()->ComputeFunction(aProximityFuncCoarse))
+ {
+ SetErrorCode("shape proximity driver failed");
+ return NULL;
+ }
+ }
+ catch (Standard_Failure& aFail)
+ {
+ SetErrorCode(aFail.GetMessageString());
+ return NULL;
+ }
+
+ //Make a Python command
+ GEOM::TPythonDump(aProximityFuncCoarse) << "p = geompy.ShapeProximity()";
+ GEOM::TPythonDump(aProximityFuncCoarse) << "p.setShapes(" << theShape1 << ", " << theShape2 << ")";
+
+ SetErrorCode(OK);
+ return aProximityCalc;
+}
+
+//=======================================================================
+//function : SetShapeSampling
+//purpose : set number sample points to compute the coarse proximity
+//=======================================================================
+void GEOMImpl_IMeasureOperations::SetShapeSampling(
+ Handle(GEOM_Object) theCalculator,
+ Handle(GEOM_Object) theShape,
+ const Standard_Integer theNbSamples)
+{
+ SetErrorCode(KO);
+ if (theShape.IsNull() ||
+ theCalculator.IsNull() ||
+ theCalculator->GetNbFunctions() <= 0 ||
+ theNbSamples <= 0)
+ return ;
+
+
+ Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
+ if (aProximityFuncCoarse.IsNull() ||
+ aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
+ return ;
+
+ Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction();
+ if (aShapeFunc.IsNull())
+ return ;
+
+ GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
+ Handle(GEOM_Function) aShape1, aShape2;
+ aProximity.GetShapes(aShape1, aShape2);
+ if (aShape1 == aShapeFunc)
+ aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
+ else if (aShape2 == aShapeFunc)
+ aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
+
+ //Make a Python command
+ GEOM::TPythonDump(aProximityFuncCoarse) << "p.setSampling(" << theShape << ", " << theNbSamples << ")";
+
+ SetErrorCode(OK);
+}
+
+//=======================================================================
+//function : GetCoarseProximity
+//purpose : compute coarse proximity
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator)
+{
+ SetErrorCode(KO);
+ if (theCalculator.IsNull())
+ return NULL;
+
+ Handle(GEOM_Function) aProximityFuncCoarse;
+ for (int i = 1; i <= theCalculator->GetNbFunctions() && aProximityFuncCoarse.IsNull(); ++i)
+ {
+ Handle(GEOM_Function) aFunc = theCalculator->GetFunction(i);
+ if (!aFunc.IsNull() && aFunc->GetType() == PROXIMITY_COARSE)
+ aProximityFuncCoarse = aFunc;
+ }
+ //Check if the function is set correctly
+ if (aProximityFuncCoarse.IsNull() ||
+ aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
+ return NULL;
+
+ GEOMImpl_IProximity aProximity(aProximityFuncCoarse);
+
+ //Make a Python command
+ GEOM::TPythonDump(aProximityFuncCoarse) << "value = p.coarseProximity()";
+
+ SetErrorCode(OK);
+ return aProximity.GetValue();
+}
+
+//=======================================================================
+//function : GetPreciseProximity
+//purpose : compute precise proximity
+//=======================================================================
+Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
+{
+ SetErrorCode(KO);
+ if (theCalculator.IsNull())
+ return NULL;
+
+ Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetLastFunction();
+ if (aProximityFuncFine.IsNull())
+ {
+ // perform coarse computatiuon beforehand
+ GetCoarseProximity(theCalculator);
+ aProximityFuncFine = theCalculator->GetLastFunction();
+ }
+ if (aProximityFuncFine->GetType() != PROXIMITY_PRECISE)
+ aProximityFuncFine = theCalculator->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
+ Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
+ //Check if the functions are set correctly
+ if (aProximityFuncCoarse.IsNull() ||
+ aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
+ aProximityFuncFine.IsNull() ||
+ aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
+ return NULL;
+
+ // transfer parameters from the coarse to precise calculator
+ GEOMImpl_IProximity aCoarseProximity(aProximityFuncCoarse);
+ Handle(GEOM_Function) aShape1, aShape2;
+ aCoarseProximity.GetShapes(aShape1, aShape2);
+ if (aShape1.IsNull() || aShape2.IsNull())
+ return NULL;
+ gp_Pnt aProxPnt1, aProxPnt2;
+ aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
+
+ GEOMImpl_IProximity aFineProximity(aProximityFuncFine);
+ aFineProximity.SetShapes(aShape1, aShape2);
+ aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
+
+ // Perform
+ try
+ {
+ OCC_CATCH_SIGNALS;
+ if (!GetSolver()->ComputeFunction(aProximityFuncFine))
+ {
+ SetErrorCode("shape proximity driver failed");
+ return NULL;
+ }
+ }
+ catch (Standard_Failure& aFail)
+ {
+ SetErrorCode(aFail.GetMessageString());
+ return NULL;
+ }
+
+ //Make a Python command
+ GEOM::TPythonDump(aProximityFuncCoarse) << "value = p.preciseProximity()";
+
+ SetErrorCode(OK);
+ return aFineProximity.GetValue();
+}
diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx
index d896b5da1..a14a01893 100644
--- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx
+++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx
@@ -244,6 +244,15 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations {
Handle(GEOM_Object) thePoint,
Handle(GEOM_Object) theDirection);
+ // Methods to compute proximity between two shapes
+ Standard_EXPORT Handle(GEOM_Object) ShapeProximityCalculator(Handle(GEOM_Object) theShape1,
+ Handle(GEOM_Object) theShape2);
+ Standard_EXPORT Standard_Real GetCoarseProximity(Handle(GEOM_Object) theCalculator);
+ Standard_EXPORT Standard_Real GetPreciseProximity(Handle(GEOM_Object) theCalculator);
+ Standard_EXPORT void SetShapeSampling(Handle(GEOM_Object) theCalculator,
+ Handle(GEOM_Object) theShape,
+ const Standard_Integer theNbSamples);
+
private:
void FillErrorsSub
diff --git a/src/GEOMImpl/GEOMImpl_IProximity.hxx b/src/GEOMImpl/GEOMImpl_IProximity.hxx
new file mode 100644
index 000000000..48b0854e8
--- /dev/null
+++ b/src/GEOMImpl/GEOMImpl_IProximity.hxx
@@ -0,0 +1,98 @@
+// Copyright (C) 2022-2022 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// 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
+//
+
+#include
+
+#define PROXIMITY_ARG_SHAPE1 1
+#define PROXIMITY_ARG_SHAPE2 2
+#define PROXIMITY_ARG_SAMPLES1 3
+#define PROXIMITY_ARG_SAMPLES2 4
+#define PROXIMITY_ARG_POINT1 5
+#define PROXIMITY_ARG_POINT2 6
+#define PROXIMITY_ARG_VALUE 7
+
+class GEOMImpl_IProximity
+{
+public:
+
+ GEOMImpl_IProximity(Handle(GEOM_Function) theFunction) : _func(theFunction) {}
+
+ void SetShapes(Handle(GEOM_Function) theShape1, Handle(GEOM_Function) theShape2)
+ {
+ _func->SetReference(PROXIMITY_ARG_SHAPE1, theShape1);
+ _func->SetReference(PROXIMITY_ARG_SHAPE2, theShape2);
+ }
+
+ void GetShapes(Handle(GEOM_Function)& theShape1, Handle(GEOM_Function)& theShape2) const
+ {
+ theShape1 = _func->GetReference(PROXIMITY_ARG_SHAPE1);
+ theShape2 = _func->GetReference(PROXIMITY_ARG_SHAPE2);
+ }
+
+ void SetNbSamples(const Standard_Integer thePosition, const Standard_Integer theNbSamples) const
+ {
+ _func->SetInteger(thePosition, theNbSamples);
+ }
+
+ Standard_Integer GetNbSamples(const Standard_Integer thePosition) const
+ {
+ return _func->GetInteger(thePosition);
+ }
+
+ void SetProximityPoints(const gp_Pnt& thePoint1, const gp_Pnt& thePoint2)
+ {
+ setPoint(PROXIMITY_ARG_POINT1, thePoint1);
+ setPoint(PROXIMITY_ARG_POINT2, thePoint2);
+ }
+
+ void GetProximityPoints(gp_Pnt& thePoint1, gp_Pnt& thePoint2)
+ {
+ thePoint1 = getPoint(PROXIMITY_ARG_POINT1);
+ thePoint2 = getPoint(PROXIMITY_ARG_POINT2);
+ }
+
+ void SetValue(const Standard_Real theValue)
+ {
+ _func->SetReal(PROXIMITY_ARG_VALUE, theValue);
+ }
+
+ Standard_Real GetValue() const
+ {
+ return _func->GetReal(PROXIMITY_ARG_VALUE);
+ }
+
+private:
+ void setPoint(const Standard_Integer thePosition, const gp_Pnt& thePoint)
+ {
+ Handle(TColStd_HArray1OfReal) aCoords = new TColStd_HArray1OfReal(1, 3);
+ aCoords->SetValue(1, thePoint.X());
+ aCoords->SetValue(2, thePoint.Y());
+ aCoords->SetValue(3, thePoint.Z());
+ _func->SetRealArray(thePosition, aCoords);
+ }
+
+ gp_Pnt getPoint(const Standard_Integer thePosition)
+ {
+ Handle(TColStd_HArray1OfReal) aCoords = _func->GetRealArray(thePosition);
+ return gp_Pnt(aCoords->Value(1), aCoords->Value(2), aCoords->Value(3));
+ }
+
+private:
+ Handle(GEOM_Function) _func;
+};
diff --git a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx
new file mode 100644
index 000000000..db69b443d
--- /dev/null
+++ b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx
@@ -0,0 +1,295 @@
+// Copyright (C) 2022-2022 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// 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
+//
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace {
+ static void tessellateShape(const TopoDS_Shape& theShape)
+ {
+ Standard_Boolean isTessellate = Standard_False;
+ TopLoc_Location aLoc;
+ for (TopExp_Explorer anExp(theShape, TopAbs_FACE); anExp.More() && !isTessellate; anExp.Next())
+ {
+ Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation(TopoDS::Face(anExp.Value()), aLoc);
+ isTessellate = aTria.IsNull();
+ }
+ for (TopExp_Explorer anExp(theShape, TopAbs_EDGE); anExp.More() && !isTessellate; anExp.Next())
+ {
+ Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(TopoDS::Edge(anExp.Value()), aLoc);
+ isTessellate = aPoly.IsNull();
+ }
+
+ if (isTessellate)
+ {
+ BRepMesh_IncrementalMesh aMesher(theShape, 0.1);
+ Standard_ProgramError_Raise_if(!aMesher.IsDone(), "Meshing failed");
+ }
+ }
+
+ static Standard_Real paramOnCurve(const BRepAdaptor_Curve& theCurve, const gp_Pnt& thePoint, const Standard_Real theTol)
+ {
+ Extrema_ExtPC aParamSearch(thePoint, theCurve, theCurve.FirstParameter(), theCurve.LastParameter());
+ if (aParamSearch.IsDone())
+ {
+ Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
+ Standard_Real aSqDistMin = RealLast();
+ for (Standard_Integer i = 1; i <= aNbExt; ++i)
+ {
+ if (aParamSearch.SquareDistance(i) < aSqDistMin)
+ {
+ anIndMin = i;
+ aSqDistMin = aParamSearch.SquareDistance(i);
+ }
+ }
+ if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
+ {
+ return aParamSearch.Point(anIndMin).Parameter();
+ }
+ }
+ return 0.5 * (theCurve.FirstParameter() + theCurve.LastParameter());
+ }
+
+ static void paramsOnSurf(const BRepAdaptor_Surface& theSurf, const gp_Pnt& thePoint, const Standard_Real theTol,
+ Standard_Real& theU, Standard_Real& theV)
+ {
+ Extrema_ExtPS aParamSearch(thePoint, theSurf, Precision::PConfusion(), Precision::PConfusion());
+ if (aParamSearch.IsDone())
+ {
+ Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
+ Standard_Real aSqDistMin = RealLast();
+ for (Standard_Integer i = 1; i <= aNbExt; ++i)
+ {
+ if (aParamSearch.SquareDistance(i) < aSqDistMin)
+ {
+ anIndMin = i;
+ aSqDistMin = aParamSearch.SquareDistance(i);
+ }
+ }
+ if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
+ {
+ return aParamSearch.Point(anIndMin).Parameter(theU, theV);
+ }
+ }
+ theU = 0.5 * (theSurf.FirstUParameter() + theSurf.LastUParameter());
+ theV = 0.5 * (theSurf.FirstVParameter() + theSurf.LastVParameter());
+ }
+
+ static Standard_Real extremaEE(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2,
+ gp_Pnt& thePoint1, gp_Pnt& thePoint2)
+ {
+ BRepAdaptor_Curve aCurve1(theEdge1);
+ BRepAdaptor_Curve aCurve2(theEdge2);
+
+ Standard_Real aU1 = paramOnCurve(aCurve1, thePoint1, BRep_Tool::Tolerance(theEdge1));
+ Standard_Real aU2 = paramOnCurve(aCurve2, thePoint2, BRep_Tool::Tolerance(theEdge2));
+
+ Standard_Real aValue = -1.0;
+ Extrema_LocateExtCC anExtr(aCurve1, aCurve2, aU1, aU2);
+ if (anExtr.IsDone())
+ {
+ aValue = Sqrt(anExtr.SquareDistance());
+
+ Extrema_POnCurv aP1, aP2;
+ anExtr.Point(aP1, aP2);
+ thePoint1 = aP1.Value();
+ thePoint2 = aP2.Value();
+ }
+ return aValue;
+ }
+
+ static Standard_Real extremaEF(const TopoDS_Edge& theEdge, const TopoDS_Face& theFace,
+ gp_Pnt& thePonE, gp_Pnt& thePonF)
+ {
+ BRepAdaptor_Curve aCurve(theEdge);
+ BRepAdaptor_Surface aSurf(theFace);
+
+ Standard_Real aP = paramOnCurve(aCurve, thePonE, BRep_Tool::Tolerance(theEdge));
+ Standard_Real aU, aV;
+ paramsOnSurf(aSurf, thePonF, BRep_Tool::Tolerance(theFace), aU, aV);
+
+ Standard_Real aValue = -1.0;
+ Extrema_GenLocateExtCS anExtr(aCurve, aSurf, aP, aU, aV, Precision::PConfusion(), Precision::PConfusion());
+ if (anExtr.IsDone())
+ {
+ aValue = Sqrt(anExtr.SquareDistance());
+ thePonE = anExtr.PointOnCurve().Value();
+ thePonF = anExtr.PointOnSurface().Value();
+ }
+ return aValue;
+ }
+
+ static Standard_Real extremaFF(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2,
+ gp_Pnt& thePoint1, gp_Pnt& thePoint2)
+ {
+ BRepAdaptor_Surface aSurf1(theFace1);
+ BRepAdaptor_Surface aSurf2(theFace2);
+
+ Standard_Real aU1, aV1;
+ paramsOnSurf(aSurf1, thePoint1, BRep_Tool::Tolerance(theFace1), aU1, aV1);
+ Standard_Real aU2, aV2;
+ paramsOnSurf(aSurf2, thePoint2, BRep_Tool::Tolerance(theFace2), aU2, aV2);
+
+ Standard_Real aValue = -1.0;
+ Extrema_GenLocateExtSS anExtr(aSurf1, aSurf2, aU1, aV1, aU2, aV2, Precision::PConfusion(), Precision::PConfusion());
+ if (anExtr.IsDone())
+ {
+ aValue = Sqrt(anExtr.SquareDistance());
+ thePoint1 = anExtr.PointOnS1().Value();
+ thePoint2 = anExtr.PointOnS2().Value();
+ }
+ return aValue;
+ }
+}
+
+//=======================================================================
+//function : GetID
+//purpose :
+//=======================================================================
+const Standard_GUID& GEOMImpl_ShapeProximityDriver::GetID()
+{
+ static Standard_GUID aShapeProximityDriver("1C3449A6-E4EB-407D-B623-89261C4BA785");
+ return aShapeProximityDriver;
+}
+
+//=======================================================================
+//function : Execute
+//purpose :
+//=======================================================================
+Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook)& log) const
+{
+ if (Label().IsNull())
+ return 0;
+
+ Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
+ GEOMImpl_IProximity aProximity(aFunction);
+
+ Handle(GEOM_Function) aShapeFunc1, aShapeFunc2;
+ aProximity.GetShapes(aShapeFunc1, aShapeFunc2);
+ if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
+ return 0;
+
+ TopoDS_Shape aShape1 = aShapeFunc1->GetValue();
+ TopoDS_Shape aShape2 = aShapeFunc2->GetValue();
+
+ Standard_Real aValue = -1.0;
+
+ if (aFunction->GetType() == PROXIMITY_COARSE)
+ {
+ // tessellate shapes if there is no mesh exists
+ tessellateShape(aShape1);
+ tessellateShape(aShape2);
+
+ // compute proximity basing of the tessellation
+ BRepExtrema_ShapeProximity aCalcProx;
+ aCalcProx.LoadShape1(aShape1);
+ aCalcProx.LoadShape2(aShape2);
+ aCalcProx.SetNbSamples1(aProximity.GetNbSamples(PROXIMITY_ARG_SAMPLES1));
+ aCalcProx.SetNbSamples2(aProximity.GetNbSamples(PROXIMITY_ARG_SAMPLES2));
+ aCalcProx.Perform();
+
+ if (aCalcProx.IsDone())
+ {
+ aValue = aCalcProx.Proximity();
+ aProximity.SetProximityPoints(aCalcProx.ProximityPoint1(),
+ aCalcProx.ProximityPoint2());
+ }
+ else
+ Standard_ConstructionError::Raise("Failed to compute coarse proximity");
+ }
+ else if (aFunction->GetType() == PROXIMITY_PRECISE)
+ {
+ TopAbs_ShapeEnum aType1 = aShape1.ShapeType();
+ TopAbs_ShapeEnum aType2 = aShape2.ShapeType();
+
+ gp_Pnt aP1, aP2;
+ aProximity.GetProximityPoints(aP1, aP2);
+
+ if (aType1 == TopAbs_EDGE)
+ {
+ if (aType2 == TopAbs_EDGE)
+ aValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aP1, aP2);
+ else if (aType2 == TopAbs_FACE)
+ aValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aP1, aP2);
+ }
+ else if (aType1 == TopAbs_FACE)
+ {
+ if (aType2 == TopAbs_EDGE)
+ aValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aP2, aP1);
+ else if (aType2 == TopAbs_FACE)
+ aValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aP1, aP2);
+ }
+
+ if (aValue >= 0)
+ aProximity.SetProximityPoints(aP1, aP2);
+ else
+ Standard_ConstructionError::Raise("Failed to compute precise proximity");
+ }
+ else
+ {
+ Standard_ConstructionError::Raise("incorrect algorithm");
+ }
+
+ aProximity.SetValue(aValue);
+ log->SetTouched(Label());
+ return 1;
+}
+
+//=======================================================================
+//function : GetCreationInformation
+//purpose : Returns a name of creation operation and names and values of creation parameters
+//=======================================================================
+bool GEOMImpl_ShapeProximityDriver::GetCreationInformation(
+ std::string& theOperationName,
+ std::vector& theParams)
+{
+ if (Label().IsNull())
+ return false;
+
+ Handle(GEOM_Function) aFunc = GEOM_Function::GetFunction(Label());
+ GEOMImpl_IProximity aProxFunc(aFunc);
+ Handle(GEOM_Function) aShape1, aShape2;
+ aProxFunc.GetShapes(aShape1, aShape2);
+
+ if (aFunc->GetType() == PROXIMITY_COARSE)
+ theOperationName = "PROXIMITY_COARSE";
+ else if (aFunc->GetType() == PROXIMITY_PRECISE)
+ theOperationName = "PROXIMITY_PRECISE";
+
+ AddParam(theParams, "Shape1", aShape1);
+ AddParam(theParams, "Shape2", aShape2);
+
+ return false;
+}
+
+IMPLEMENT_STANDARD_RTTIEXT(GEOMImpl_ShapeProximityDriver, GEOM_BaseDriver)
diff --git a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.hxx b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.hxx
new file mode 100644
index 000000000..3a1312e2f
--- /dev/null
+++ b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.hxx
@@ -0,0 +1,45 @@
+// Copyright (C) 2022-2022 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// 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
+//
+#ifndef _GEOMImpl_ShapeProximityDriver_HeaderFile
+#define _GEOMImpl_ShapeProximityDriver_HeaderFile
+
+#include
+
+DEFINE_STANDARD_HANDLE(GEOMImpl_ShapeProximityDriver, GEOM_BaseDriver)
+
+class GEOMImpl_ShapeProximityDriver : public GEOM_BaseDriver {
+
+public:
+
+ Standard_EXPORT GEOMImpl_ShapeProximityDriver() {}
+ Standard_EXPORT virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
+ Standard_EXPORT virtual void Validate(Handle(TFunction_Logbook)&) const {}
+ Standard_EXPORT Standard_Boolean MustExecute(const Handle(TFunction_Logbook)&) const { return Standard_True; }
+
+ Standard_EXPORT static const Standard_GUID& GetID();
+ Standard_EXPORT ~GEOMImpl_ShapeProximityDriver() {}
+
+ Standard_EXPORT virtual
+ bool GetCreationInformation(std::string& theOperationName,
+ std::vector& params);
+
+ DEFINE_STANDARD_RTTIEXT(GEOMImpl_ShapeProximityDriver, GEOM_BaseDriver)
+};
+
+#endif
diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx
index fec26368a..8984fe939 100644
--- a/src/GEOMImpl/GEOMImpl_Types.hxx
+++ b/src/GEOMImpl/GEOMImpl_Types.hxx
@@ -125,6 +125,7 @@
#define GEOM_PATCH_FACE 60
+#define GEOM_SHAPE_PROXIMITY 61
#define GEOM_CHECKCONFORMITY 62
//GEOM_Function types
@@ -365,6 +366,10 @@
#define VERTEX_BY_INDEX 5
#define CURVATURE_VEC_MEASURE 6
+// Proximity algorithms
+#define PROXIMITY_COARSE 1
+#define PROXIMITY_PRECISE 2
+
#define GROUP_FUNCTION 1
// Curve constructor type
diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.cc b/src/GEOM_I/GEOM_IMeasureOperations_i.cc
index c2bffa8e9..a41f597d0 100644
--- a/src/GEOM_I/GEOM_IMeasureOperations_i.cc
+++ b/src/GEOM_I/GEOM_IMeasureOperations_i.cc
@@ -1443,3 +1443,97 @@ void GEOM_IMeasureOperations_i::ConvertToList(const GEOM::GEOM_IMeasureOperation
theListOfResults.push_back(aCheck);
}
}
+
+//=============================================================================
+/*!
+ * ShapeProximityCalculator
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_IMeasureOperations_i::ShapeProximityCalculator(GEOM::GEOM_Object_ptr theShape1,
+ GEOM::GEOM_Object_ptr theShape2)
+{
+ GEOM::GEOM_Object_var anEmptyCalc;
+
+ //Set a not done flag
+ GetOperations()->SetNotDone();
+
+ //Get the reference shape
+ Handle(::GEOM_Object) aShape1 = GetObjectImpl(theShape1);
+ Handle(::GEOM_Object) aShape2 = GetObjectImpl(theShape2);
+ if (aShape1.IsNull() || aShape2.IsNull())
+ return anEmptyCalc._retn();
+
+ Handle(::GEOM_Object) aCalculator = GetOperations()->ShapeProximityCalculator(aShape1, aShape2);
+ if (!GetOperations()->IsDone() || aCalculator.IsNull())
+ return anEmptyCalc._retn();
+
+ return GetObject(aCalculator);
+}
+
+//=============================================================================
+/*!
+ * SetShapeSampling
+ */
+ //=============================================================================
+void GEOM_IMeasureOperations_i::SetShapeSampling(GEOM::GEOM_Object_ptr theCalculator,
+ GEOM::GEOM_Object_ptr theShape,
+ long theNbSamples)
+{
+ //Set a not done flag
+ GetOperations()->SetNotDone();
+
+ //Get the proximity calculator
+ Handle(::GEOM_Object) aCalc = GetObjectImpl(theCalculator);
+ if (aCalc.IsNull())
+ return ;
+ //Get the reference shape
+ Handle(::GEOM_Object) aShape = GetObjectImpl(theShape);
+ if (aShape.IsNull())
+ return ;
+
+ GetOperations()->SetShapeSampling(aCalc, aShape, theNbSamples);
+}
+
+//=============================================================================
+/*!
+ * GetCoarseProximity
+ */
+ //=============================================================================
+CORBA::Double GEOM_IMeasureOperations_i::GetCoarseProximity(GEOM::GEOM_Object_ptr theCalculator)
+{
+ //Set a not done flag
+ GetOperations()->SetNotDone();
+
+ //Get the reference shape
+ Handle(::GEOM_Object) aCalc = GetObjectImpl(theCalculator);
+ if (aCalc.IsNull())
+ return -1.0;
+
+ Standard_Real aProximity = GetOperations()->GetCoarseProximity(aCalc);
+ if (!GetOperations()->IsDone())
+ return -1.0;
+
+ return aProximity;
+}
+
+//=============================================================================
+/*!
+ * GetPreciseProximity
+ */
+ //=============================================================================
+CORBA::Double GEOM_IMeasureOperations_i::GetPreciseProximity(GEOM::GEOM_Object_ptr theCalculator)
+{
+ //Set a not done flag
+ GetOperations()->SetNotDone();
+
+ //Get the reference shape
+ Handle(::GEOM_Object) aCalc = GetObjectImpl(theCalculator);
+ if (aCalc.IsNull())
+ return -1.0;
+
+ Standard_Real aProximity = GetOperations()->GetPreciseProximity(aCalc);
+ if (!GetOperations()->IsDone())
+ return -1.0;
+
+ return aProximity;
+}
diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.hh b/src/GEOM_I/GEOM_IMeasureOperations_i.hh
index 630218c04..bcaf83c98 100644
--- a/src/GEOM_I/GEOM_IMeasureOperations_i.hh
+++ b/src/GEOM_I/GEOM_IMeasureOperations_i.hh
@@ -191,6 +191,15 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i :
CORBA::Double UpdateTolerance(GEOM::GEOM_Object_ptr theShape);
+ // Methods to compute proximity between two shapes
+ GEOM::GEOM_Object_ptr ShapeProximityCalculator (GEOM::GEOM_Object_ptr theShape1,
+ GEOM::GEOM_Object_ptr theShape2);
+ void SetShapeSampling(GEOM::GEOM_Object_ptr theCalculator,
+ GEOM::GEOM_Object_ptr theShape,
+ long theNbSamples);
+ CORBA::Double GetCoarseProximity(GEOM::GEOM_Object_ptr theCalculator);
+ CORBA::Double GetPreciseProximity(GEOM::GEOM_Object_ptr theCalculator);
+
::GEOMImpl_IMeasureOperations* GetOperations()
{ return (::GEOMImpl_IMeasureOperations*)GetImpl(); }
diff --git a/src/GEOM_SWIG/CMakeLists.txt b/src/GEOM_SWIG/CMakeLists.txt
index e9b78cadc..5735fa949 100644
--- a/src/GEOM_SWIG/CMakeLists.txt
+++ b/src/GEOM_SWIG/CMakeLists.txt
@@ -73,6 +73,7 @@ SET(_python_SCRIPTS
gsketcher.py
canonicalrecognition.py
conformity.py
+ proximity.py
)
# Advanced scripts
diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py
index cf5a9dba0..d28107781 100644
--- a/src/GEOM_SWIG/geomBuilder.py
+++ b/src/GEOM_SWIG/geomBuilder.py
@@ -262,6 +262,7 @@ import functools
from salome.geom.gsketcher import Sketcher3D, Sketcher2D, Polyline2D
from salome.geom.canonicalrecognition import CanonicalRecognition
from salome.geom.conformity import CheckConformity
+from salome.geom.proximity import ShapeProximity
# In case the omniORBpy EnumItem class does not fully support Python 3
# (for instance in version 4.2.1-2), the comparison ordering methods must be
@@ -14056,6 +14057,21 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
conf = CheckConformity (shape, self)
return conf
+ ## Obtain a shape proximity calculator
+ # @return An instance of @ref proximity.ShapeProximity "ShapeProximity" interface
+ #
+ # @ref tui_proximity_page "Example"
+ def ShapeProximity (self):
+ """
+ Obtain a shape proximity calculator.
+
+ Example of usage:
+ prox = geompy.ShapeProximity()
+ value = prox.proximity(shape1, shape2)
+ """
+ prox = ShapeProximity (self)
+ return prox
+
# end of l2_testing
## @}
diff --git a/src/GEOM_SWIG/proximity.py b/src/GEOM_SWIG/proximity.py
new file mode 100644
index 000000000..d2296e120
--- /dev/null
+++ b/src/GEOM_SWIG/proximity.py
@@ -0,0 +1,91 @@
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2022-2022 CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# 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
+
+## @defgroup proximity ShapeProximity - tool to check the proximity distance between two shapes
+# @{
+# @details
+# The tool provides the user a possibility to compute the proximity distance between two shapes:
+# * a minimal diameter of a tube containing both edges (for edge-edge proximity);
+# * a minimal thickness of a shell containing both faces (for face-face proximity).
+#
+# In other words, this tool calculate maximal of all possible distances between pair of objects.
+# It is supported to compute distance between two edges or between two faces.
+# Other combinations of shapes are prohibited.
+# @}
+
+"""
+ \namespace geompy
+ \brief ShapeProximity interface
+"""
+
+## A class to compute proximity value between two shapes.
+# Use geompy.ShapeProximity() method to obtain an instance of this class.
+#
+# @ref tui_proximity_page "Example"
+# @ingroup proximity
+class ShapeProximity():
+ """
+ ShapeProximity interface.
+
+ Example of usage:
+ prox = geompy.ShapeProximity()
+ value = prox.proximity(shape1, shape2)
+ """
+
+ def __init__(self, geompyD):
+ self.myCommand = "ShapeProximity"
+ self.myOp = geompyD.GetIMeasureOperations()
+ pass
+
+ ## Computes proximity between two shapes of the same type
+ def proximity(self, shape1, shape2):
+ self.setShapes(shape1, shape2)
+ self.coarseProximity()
+ return self.preciseProximity()
+ pass
+
+ ## Customize object with the input shapes
+ def setShapes(self, shape1, shape2):
+ self.myProximityValue = None
+ from salome.geom.geomBuilder import RaiseIfFailed
+ self.myCalc = self.myOp.ShapeProximityCalculator(shape1, shape2)
+ RaiseIfFailed(self.myCommand, self.myOp)
+ pass
+
+ ## Define the minimal number of sample points for the given shape,
+ # which should be used for raw computation of proximity value
+ def setSampling(self, shape, nbSamples):
+ self.myOp.SetShapeSampling(self.myCalc, shape, nbSamples)
+ pass
+
+ ## Find rough proximity value based on polygon/tessellation representation
+ def coarseProximity(self):
+ from salome.geom.geomBuilder import RaiseIfFailed
+ self.myProximityValue = self.myOp.GetCoarseProximity(self.myCalc)
+ RaiseIfFailed(self.myCommand, self.myOp)
+ return self.myProximityValue
+ pass
+
+ ## Find precise proximity value based on exact shapes
+ def preciseProximity(self):
+ from salome.geom.geomBuilder import RaiseIfFailed
+ self.myProximityValue = self.myOp.GetPreciseProximity(self.myCalc)
+ RaiseIfFailed(self.myCommand, self.myOp)
+ return self.myProximityValue
+ pass
diff --git a/test/test_proximity_edge_edge.py b/test/test_proximity_edge_edge.py
new file mode 100644
index 000000000..562310764
--- /dev/null
+++ b/test/test_proximity_edge_edge.py
@@ -0,0 +1,60 @@
+# Shape Proximity between edges
+
+import math
+import salome
+salome.salome_init_without_session()
+import GEOM
+from salome.geom import geomBuilder
+geompy = geomBuilder.New()
+
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+
+# create arc and segment
+Vertex_1 = geompy.MakeVertex(0, 0, -1)
+Vertex_2 = geompy.MakeVertex(1, 0, 0)
+Vertex_3 = geompy.MakeVertex(0, 0, 1)
+Arc_1 = geompy.MakeArc(Vertex_1, Vertex_2, Vertex_3)
+Arc_1_vertex_2 = geompy.GetSubShape(Arc_1, [2])
+Edge_1 = geompy.MakeEdgeOnCurveByLength(Arc_1, 3, Arc_1_vertex_2)
+Edge_2 = geompy.MakeEdge(Vertex_1, Vertex_3)
+
+shape1 = Edge_1
+shape2 = Edge_2
+
+# perform proximity calculation with the default parameters
+p1 = geompy.ShapeProximity()
+proximity1 = p1.proximity(shape1, shape2)
+
+# perform proximity calculation with custom parameters
+p2 = geompy.ShapeProximity()
+p2.setShapes(shape1, shape2)
+p2.setSampling(shape1, 100) # number of sample points for the first shape
+p2.setSampling(shape2, 40) # number of sample points for the second shape
+proximity2_coarse = p2.coarseProximity()
+proximity2_fine = p2.preciseProximity()
+
+assert(math.fabs(proximity1 - proximity2_fine) < 1.e-7)
+assert(math.fabs(proximity2_coarse - 0.9974949866) < 1.e-7)
+assert(math.fabs(proximity2_fine - 1) < 1.e-7)
+
+# move second edge and check proximity
+Translation_1 = geompy.MakeTranslation(Edge_2, 0.3, 0, 0)
+shape2 = Translation_1
+
+# perform proximity calculation with the default parameters
+p1 = geompy.ShapeProximity()
+proximity1 = p1.proximity(shape1, shape2)
+
+# perform proximity calculation with custom parameters
+p2 = geompy.ShapeProximity()
+p2.setShapes(shape1, shape2)
+p2.setSampling(shape1, 100) # number of sample points for the first shape
+p2.setSampling(shape2, 40) # number of sample points for the second shape
+proximity2_coarse = p2.coarseProximity()
+proximity2_fine = p2.preciseProximity()
+
+assert(math.fabs(proximity1 - 0.7) < 1.e-7)
+assert(math.fabs(proximity2_fine - 0.7) < 1.e-7)
diff --git a/test/test_proximity_face_face.py b/test/test_proximity_face_face.py
new file mode 100644
index 000000000..08e71d2b4
--- /dev/null
+++ b/test/test_proximity_face_face.py
@@ -0,0 +1,43 @@
+# Shape Proximity between faces
+
+import math
+import salome
+salome.salome_init_without_session()
+import GEOM
+from salome.geom import geomBuilder
+geompy = geomBuilder.New()
+
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+
+# create conical and planar faces
+Cone_1 = geompy.MakeConeR1R2H(100, 0, 300)
+Cone_1_face_3 = geompy.GetSubShape(Cone_1, [3])
+Cone_1_wire_4 = geompy.GetSubShape(Cone_1, [4])
+Face_1 = geompy.MakeFaceFromSurface(Cone_1_face_3, Cone_1_wire_4)
+Face_1_edge_5 = geompy.GetSubShape(Face_1, [5])
+Face_2 = geompy.MakeFaceObjHW(Face_1_edge_5, 200, 200)
+geompy.Rotate(Face_2, OY, 90*math.pi/180.0)
+Face_2_vertex_7 = geompy.GetSubShape(Face_2, [7])
+Translation_1 = geompy.MakeTranslationTwoPoints(Face_2, Face_2_vertex_7, O)
+
+shape1 = Face_1
+shape2 = Translation_1
+
+# perform proximity calculation with the default parameters
+p1 = geompy.ShapeProximity()
+proximity1 = p1.proximity(shape1, shape2)
+
+# perform proximity calculation with custom parameters
+p2 = geompy.ShapeProximity()
+p2.setShapes(shape1, shape2)
+p2.setSampling(shape1, 100) # number of sample points for the first shape
+p2.setSampling(shape2, 40) # number of sample points for the second shape
+proximity2_coarse = p2.coarseProximity()
+proximity2_fine = p2.preciseProximity()
+
+assert(math.fabs(proximity1 - proximity2_fine) < 1.e-7)
+assert(math.fabs(proximity2_coarse - 127.1141386) < 1.e-7)
+assert(math.fabs(proximity2_fine - 94.8683298) < 1.e-7)
diff --git a/test/tests.set b/test/tests.set
index 1688ac2c7..7a002556f 100644
--- a/test/tests.set
+++ b/test/tests.set
@@ -27,5 +27,7 @@ IF(${OpenCASCADE_VERSION}.${OpenCASCADE_SP_VERSION} VERSION_GREATER "7.5.3.3")
test_point_cloud_on_face.py
test_CR.py
test_conformity.py
+ test_proximity_edge_edge.py
+ test_proximity_face_face.py
)
ENDIF()