bos #29468: Advanced geometry features: distance Edge-Edge & Face-Face

This commit is contained in:
azv 2022-06-17 17:19:17 +03:00
parent a54e77dbcd
commit 1e0c8c69ad
23 changed files with 1077 additions and 0 deletions

View File

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

View File

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

View File

@ -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
<pre>
geompy.ShapeProximity()
</pre>
has an interface to compute proximity value with default parameters
<pre>
p = geompy.ShapeProximity()
value = p.proximity(shape1, shape2)
</pre>
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.
<pre>
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
</pre>
See also a \ref tui_shape_proximity_page "TUI example".
*/

View File

@ -21,6 +21,7 @@
<li>\subpage tui_check_self_intersections_page</li>
<li>\subpage tui_check_self_intersections_fast_page</li>
<li>\subpage tui_fast_intersection_page</li>
<li>\subpage tui_shape_proximity_page</li>
</ul>
*/

View File

@ -0,0 +1,6 @@
/*!
\page tui_shape_proximity_page Compute Proximity between Shapes
\tui_script{shape_proximity.py}
*/

View File

@ -21,6 +21,7 @@
<li>\subpage whatis_page "WhatIs"</li>
<li>\subpage inspect_object_operation_page "Inspect Object"</li>
<li>\subpage shape_statistics_operation_page "Shape Statistics"</li>
<li>\subpage shape_proximity_page "Shapes Proximity"</li>
</ul>
\n To check their integrity:

View File

@ -4744,6 +4744,37 @@ module GEOM
in GEOM_Object thePoint,
in GEOM_Object theDirection);
/*!
* \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:

View File

@ -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
@ -180,6 +181,7 @@ SET(GEOMImpl_HEADERS
GEOMImpl_FillingDriver.hxx
GEOMImpl_GlueDriver.hxx
GEOMImpl_PatchFaceDriver.hxx
GEOMImpl_ShapeProximityDriver.hxx
GEOMImpl_Types.hxx
GEOM_GEOMImpl.hxx
)
@ -256,6 +258,7 @@ SET(GEOMImpl_SOURCES
GEOMImpl_FillingDriver.cxx
GEOMImpl_GlueDriver.cxx
GEOMImpl_PatchFaceDriver.cxx
GEOMImpl_ShapeProximityDriver.cxx
GEOMImpl_FieldDriver.cxx
)

View File

@ -83,6 +83,7 @@
#include <GEOMImpl_GlueDriver.hxx>
#include <GEOMImpl_MeasureDriver.hxx>
#include <GEOMImpl_FieldDriver.hxx>
#include <GEOMImpl_ShapeProximityDriver.hxx>
//=============================================================================
/*!
@ -163,6 +164,7 @@ GEOMImpl_Gen::GEOMImpl_Gen()
// Measurements
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_ShapeProximityDriver::GetID(), new GEOMImpl_ShapeProximityDriver());
// Field
TFunction_DriverTable::Get()->AddDriver(GEOMImpl_FieldDriver::GetID(), new GEOMImpl_FieldDriver());

View File

@ -25,7 +25,9 @@
#include <GEOMImpl_MeasureDriver.hxx>
#include <GEOMImpl_IPatchFace.hxx>
#include <GEOMImpl_IProximity.hxx>
#include <GEOMImpl_PatchFaceDriver.hxx>
#include <GEOMImpl_ShapeProximityDriver.hxx>
#include <GEOMImpl_Types.hxx>
@ -2941,3 +2943,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();
}

View File

@ -222,6 +222,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

View File

@ -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 <GEOM_Function.hxx>
#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;
};

View File

@ -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 <GEOMImpl_ShapeProximityDriver.hxx>
#include <GEOMImpl_IProximity.hxx>
#include <GEOMImpl_Types.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepExtrema_ShapeProximity.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <Extrema_ExtPC.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_GenLocateExtCS.hxx>
#include <Extrema_GenLocateExtSS.hxx>
#include <Extrema_LocateExtCC.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
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<GEOM_Param>& 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)

View File

@ -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 <GEOM_BaseDriver.hxx>
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<GEOM_Param>& params);
DEFINE_STANDARD_RTTIEXT(GEOMImpl_ShapeProximityDriver, GEOM_BaseDriver)
};
#endif

View File

@ -125,6 +125,8 @@
#define GEOM_CURVATURE_VEC 60
#define GEOM_SHAPE_PROXIMITY 61
//GEOM_Function types
#define COPY_WITH_REF 1
@ -363,6 +365,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

View File

@ -1243,3 +1243,97 @@ GEOM::GEOM_Object_ptr GEOM_IMeasureOperations_i::SurfaceCurvatureByPointAndDirec
return GetObject(anObject);
}
//=============================================================================
/*!
* 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;
}

View File

@ -170,6 +170,15 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i :
GEOM::GEOM_Object_ptr thePoint,
GEOM::GEOM_Object_ptr theDirection);
// 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(); }
};

View File

@ -71,6 +71,7 @@ SET(_other_SCRIPTS
SET(_python_SCRIPTS
geomBuilder.py
gsketcher.py
proximity.py
)
# Advanced scripts

View File

@ -260,6 +260,7 @@ import os
import functools
from salome.geom.gsketcher import Sketcher3D, Sketcher2D, Polyline2D
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
@ -14018,6 +14019,22 @@ class geomBuilder(GEOM._objref_GEOM_Gen):
RaiseIfFailed("Tesselate", self.TestOp)
return r
## 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
## @}

View File

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

View File

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

View File

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

View File

@ -19,4 +19,6 @@
SET(ALL_TESTS
test_perf_01.py
test_proximity_edge_edge.py
test_proximity_face_face.py
)