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

This commit is contained in:
azv 2022-06-17 17:19:17 +03:00 committed by jfa
parent 901ba4f298
commit 9f73090059
25 changed files with 1397 additions and 0 deletions

View File

@ -0,0 +1,40 @@
# Shape Proximity
import math
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
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,52 @@
/*!
\page shape_proximity_page Shape Proximity
The Shape Proximity operation calculates maximal of all possible distances between two shapes.
Considering this case :
\image html Shape_proximity_0.png
The proximity of blue shape to the red one is computed like this :
For each point of blue the distance to the red is computed using perpendicular projection. The proximity value returned is equal to maximal value of all of this distances.
To do that the implemented algorithm
1 - sampling shapes by points then calculating the distance from each sample point from one shape to another
2 - find the position which gives the maximal distance
3 - improve the proximity value basing on the exact shapes using the points found on step 2 as a start position
It may happen that for some point of blue shape no distance to red shape exist using perpendicular projection.
This is typically the case here :
\image html Shape_proximity_1.png
In the case of no perpendicular projection of a point on blue shape exists, instead of perpendicular projection the minimal distance to border point of red shape is considered.
The distance from EndBlue Point is taken using EndRed Point (black line represents the distance for EndBlue).
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

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

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

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

View File

@ -84,6 +84,7 @@
#include <GEOMImpl_MeasureDriver.hxx>
#include <GEOMImpl_FieldDriver.hxx>
#include <GEOMImpl_ConformityDriver.hxx>
#include <GEOMImpl_ShapeProximityDriver.hxx>
//=============================================================================
/*!
@ -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());

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>
@ -3278,3 +3280,191 @@ 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_Function) aShapeFunc1 = theShape1->GetLastFunction();
Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction();
if (aShapeFunc1.IsNull() || aShapeFunc2.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);
aProximity.SetShapes(aShapeFunc1, aShapeFunc2);
//Make a Python command
GEOM::TPythonDump pd (aProximityFuncCoarse);
pd << "p = geompy.ShapeProximity()\n";
pd << "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->GetValue() == aShapeFunc->GetValue())
aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples);
else if (aShape2->GetValue() == aShapeFunc->GetValue())
aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples);
//Make a Python command
GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) <<
"p.setSampling(" << theShape << ", " << theNbSamples << ")";
SetErrorCode(OK);
}
//=======================================================================
//function : GetCoarseProximity
//purpose : compute coarse proximity
//=======================================================================
Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator,
bool doPythonDump)
{
SetErrorCode(KO);
if (theCalculator.IsNull())
return -1;
Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
if (aProximityFuncCoarse.IsNull() ||
aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
aProximityFuncCoarse->GetType() != PROXIMITY_COARSE)
return -1;
// Perform
// We have to recompute the function each time,
// because the number of samples can be changed
try {
OCC_CATCH_SIGNALS;
if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) {
SetErrorCode("shape proximity driver failed");
return -1;
}
}
catch (Standard_Failure& aFail) {
SetErrorCode(aFail.GetMessageString());
return -1;
}
//Make a Python command
if (doPythonDump)
GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()";
SetErrorCode(OK);
GEOMImpl_IProximity aProximity (aProximityFuncCoarse);
return aProximity.GetValue();
}
//=======================================================================
//function : GetPreciseProximity
//purpose : compute precise proximity
//=======================================================================
Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator)
{
SetErrorCode(KO);
if (theCalculator.IsNull())
return -1;
Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1);
Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2);
if (aProximityFuncFine.IsNull())
aProximityFuncFine = theCalculator->AddFunction
(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE);
//Check if the functions are set correctly
if (aProximityFuncCoarse.IsNull() ||
aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() ||
aProximityFuncFine.IsNull() ||
aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID())
return -1;
// perform coarse computation beforehand
GetCoarseProximity(theCalculator, /*doPythonDump=*/false);
// 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 -1;
gp_Pnt aProxPnt1, aProxPnt2;
Standard_Integer intStatus1, intStatus2;
aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2);
Standard_Real aResultValue = aCoarseProximity.GetValue();
GEOMImpl_IProximity aFineProximity (aProximityFuncFine);
aFineProximity.SetShapes(aShape1, aShape2);
aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2);
aFineProximity.SetStatusOfPoints(intStatus1, intStatus2);
aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised
// Perform
try {
OCC_CATCH_SIGNALS;
if (!GetSolver()->ComputeFunction(aProximityFuncFine)) {
SetErrorCode("shape proximity driver failed");
return -1;
}
}
catch (Standard_Failure& aFail) {
SetErrorCode(aFail.GetMessageString());
return -1;
}
aResultValue = aFineProximity.GetValue();
aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2);
//Make a Python command
GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()";
SetErrorCode(OK);
return aResultValue;
}

View File

@ -244,6 +244,16 @@ 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,
bool doPythonDump = true);
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,122 @@
// 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
#define PROXIMITY_ARG_STATUS1 8
#define PROXIMITY_ARG_STATUS2 9
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 SetStatusOfPoints(const Standard_Integer theStatus1, const Standard_Integer theStatus2)
{
setStatus(PROXIMITY_ARG_STATUS1, theStatus1);
setStatus(PROXIMITY_ARG_STATUS2, theStatus2);
}
void GetProximityPoints(gp_Pnt& thePoint1, gp_Pnt& thePoint2)
{
thePoint1 = getPoint(PROXIMITY_ARG_POINT1);
thePoint2 = getPoint(PROXIMITY_ARG_POINT2);
}
void GetStatusOfPoints(Standard_Integer& theStatus1, Standard_Integer& theStatus2)
{
theStatus1 = getStatus(PROXIMITY_ARG_STATUS1);
theStatus2 = getStatus(PROXIMITY_ARG_STATUS2);
}
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);
}
void setStatus(const Standard_Integer thePosition, const Standard_Integer theStatus)
{
_func->SetInteger(thePosition, theStatus);
}
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));
}
Standard_Integer getStatus(const Standard_Integer thePosition)
{
return _func->GetInteger(thePosition);
}
private:
Handle(GEOM_Function) _func;
};

View File

@ -0,0 +1,457 @@
// 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_GenLocateExtPS.hxx>
#include <Extrema_LocateExtCC.hxx>
#include <Extrema_LocateExtPC.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);
TopLoc_Location aLoc;
Standard_Real aTol1 = BRep_Tool::Tolerance(theEdge1);
Handle(Poly_Polygon3D) aPoly1 = BRep_Tool::Polygon3D (theEdge1, aLoc);
if (!aPoly1.IsNull())
aTol1 = Max (aTol1, aPoly1->Deflection());
Standard_Real aTol2 = BRep_Tool::Tolerance(theEdge2);
Handle(Poly_Polygon3D) aPoly2 = BRep_Tool::Polygon3D (theEdge2, aLoc);
if (!aPoly2.IsNull())
aTol2 = Max (aTol2, aPoly2->Deflection());
Standard_Real aU1 = paramOnCurve(aCurve1, thePoint1, 2*aTol1);
Standard_Real aU2 = paramOnCurve(aCurve2, thePoint2, 2*aTol2);
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 extremaPE(const gp_Pnt& thePoint,
const TopoDS_Edge& theEdge,
gp_Pnt& thePointOnEdge)
{
BRepAdaptor_Curve aCurve (theEdge);
TopLoc_Location aLoc;
Standard_Real aTol = BRep_Tool::Tolerance(theEdge);
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D (theEdge, aLoc);
if (!aPoly.IsNull())
aTol = Max (aTol, aPoly->Deflection());
Standard_Real aParam = paramOnCurve (aCurve, thePointOnEdge, 2*aTol);
Standard_Real aValue = -1.0;
Extrema_LocateExtPC anExtr (thePoint, aCurve, aParam, Precision::PConfusion());
if (anExtr.IsDone())
{
aValue = Sqrt(anExtr.SquareDistance());
Extrema_POnCurv aPointOnCurve = anExtr.Point();
thePointOnEdge = aPointOnCurve.Value();
}
return aValue;
}
static Standard_Real extremaPF(const gp_Pnt& thePoint,
const TopoDS_Face& theFace,
gp_Pnt& thePointOnFace)
{
BRepAdaptor_Surface aSurf (theFace);
TopLoc_Location aLoc;
Standard_Real aTol = BRep_Tool::Tolerance(theFace);
Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation (theFace, aLoc);
if (!aTria.IsNull())
aTol = Max (aTol, aTria->Deflection());
Standard_Real aU, aV;
paramsOnSurf(aSurf, thePointOnFace, 2*aTol, aU, aV);
Standard_Real aValue = -1.0;
Extrema_GenLocateExtPS anExtr (aSurf);
anExtr.Perform (thePoint, aU, aV);
if (anExtr.IsDone())
{
aValue = Sqrt(anExtr.SquareDistance());
Extrema_POnSurf aPointOnSurf = anExtr.Point();
thePointOnFace = aPointOnSurf.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);
TopLoc_Location aLoc;
Standard_Real aTolEdge = BRep_Tool::Tolerance(theEdge);
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D (theEdge, aLoc);
if (!aPoly.IsNull())
aTolEdge = Max (aTolEdge, aPoly->Deflection());
Standard_Real aTolFace = BRep_Tool::Tolerance(theFace);
Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation (theFace, aLoc);
if (!aTria.IsNull())
aTolFace = Max (aTolFace, aTria->Deflection());
Standard_Real aP = paramOnCurve(aCurve, thePonE, 2*aTolEdge);
Standard_Real aU, aV;
paramsOnSurf(aSurf, thePonF, 2*aTolFace, 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);
TopLoc_Location aLoc;
Standard_Real aTol1 = BRep_Tool::Tolerance(theFace1);
Handle(Poly_Triangulation) aTria1 = BRep_Tool::Triangulation (theFace1, aLoc);
if (!aTria1.IsNull())
aTol1 = Max (aTol1, aTria1->Deflection());
Standard_Real aTol2 = BRep_Tool::Tolerance(theFace2);
Handle(Poly_Triangulation) aTria2 = BRep_Tool::Triangulation (theFace2, aLoc);
if (!aTria2.IsNull())
aTol2 = Max (aTol2, aTria2->Deflection());
Standard_Real aU1, aV1;
paramsOnSurf(aSurf1, thePoint1, 2*aTol1, aU1, aV1);
Standard_Real aU2, aV2;
paramsOnSurf(aSurf2, thePoint2, 2*aTol2, 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 on 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());
aProximity.SetStatusOfPoints((Standard_Integer)aCalcProx.ProxPntStatus1(),
(Standard_Integer)aCalcProx.ProxPntStatus2());
}
else
Standard_ConstructionError::Raise("Failed to compute coarse proximity");
}
else if (aFunction->GetType() == PROXIMITY_PRECISE)
{
// coarse proximity value
// in some cases this value cannot be precised
// it can be precised only if at least one point is in the middle of the shape
aValue = aProximity.GetValue();
TopAbs_ShapeEnum aType1 = aShape1.ShapeType();
TopAbs_ShapeEnum aType2 = aShape2.ShapeType();
gp_Pnt aPnt1, aPnt2;
BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus1, aStatus2;
Standard_Integer intStatus1, intStatus2;
aProximity.GetProximityPoints(aPnt1, aPnt2);
aProximity.GetStatusOfPoints(intStatus1, intStatus2);
aStatus1 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus1;
aStatus2 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus2;
if (aType1 == TopAbs_EDGE)
{
if (aType2 == TopAbs_EDGE)
{
if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aPnt1, aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
{
aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
}
}
else if (aType2 == TopAbs_FACE)
{
if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
{
aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
}
}
}
else if (aType1 == TopAbs_FACE)
{
if (aType2 == TopAbs_EDGE)
{
if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aPnt2, aPnt1);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
{
aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
}
}
else if (aType2 == TopAbs_FACE)
{
if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
{
aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
}
else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
{
aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
}
}
}
if (aValue >= 0)
aProximity.SetProximityPoints(aPnt1, aPnt2);
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,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

View File

@ -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,
CORBA::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

@ -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,
CORBA::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

@ -73,6 +73,7 @@ SET(_python_SCRIPTS
gsketcher.py
canonicalrecognition.py
conformity.py
proximity.py
)
# Advanced scripts

View File

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

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,130 @@
# 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)
# Case 1: two bezier curves (original Cas2_29468.py)
from math import sqrt
# 283x384
szY = 384
listOfPtsRed_gimp = [(10,84), (54,96),(145,146),(167,167),(185,212),(187,234),(176,302)]
listOfPtsBlue_gimp = [(120,72),(170,87),(227,118),(238,126),(243,157),(203,216),(134,281),(94,324)]
#
listOfPtsRed = [(x,szY-y) for x,y in listOfPtsRed_gimp]
listOfPtsBlue = [(x,szY-y) for x,y in listOfPtsBlue_gimp]
#
verticesRed = [geompy.MakeVertex(x,y,0) for x,y in listOfPtsRed]
verticesBlue = [geompy.MakeVertex(x,y,0) for x,y in listOfPtsBlue]
for i,(x,y) in enumerate(listOfPtsRed):
geompy.addToStudy(geompy.MakeVertex(x,y,0),"red_pt{}".format(i))
for i,(x,y) in enumerate(listOfPtsBlue):
geompy.addToStudy(geompy.MakeVertex(x,y,0),"blue_pt{}".format(i))
redEdge = geompy.MakeBezier(verticesRed)
blueEdge = geompy.MakeBezier(verticesBlue)
#
geompy.addToStudy(redEdge,"red")
geompy.addToStudy(blueEdge,"blue")
XY_red = (152,214)
XY_blue = (215,260)
exp_red = geompy.MakeVertex(*XY_red,0)
exp_blue = geompy.MakeVertex(*XY_blue,0)
geompy.addToStudy(exp_red,"exp_red")
geompy.addToStudy(exp_blue,"exp_blue")
p = geompy.ShapeProximity()
p.setShapes(redEdge, blueEdge)
p.setSampling(redEdge, 1000)
p.setSampling(blueEdge, 1000)
p_coarse = p.coarseProximity()
p_precise = p.preciseProximity()
print( "coarse = {} ; fine = {}".format(p_coarse,p_precise) )
print( "Manually obtained value = {}".format( sqrt( (XY_red[0]-XY_blue[0])**2 + (XY_red[1]-XY_blue[1])**2 ) ) )
assert(math.fabs(p_coarse - 223.00892775) < 1.e-7)
prev = geompy.ShapeProximity()
prev.setShapes(blueEdge, redEdge)
prev.setSampling(redEdge, 1000)
prev.setSampling(blueEdge, 1000)
p_coarse = prev.coarseProximity()
p_precise = prev.preciseProximity()
print( "coarse = {} ; fine = {}".format(p_coarse,p_precise) )
assert(math.fabs(p_coarse - 84.89994110) < 1.e-7)
# Case 2: two bezier curves (different coarse and fine proximities)
V1 = geompy.MakeVertex(10, 10, 0)
V2 = geompy.MakeVertex(20, -10, 0)
V3 = geompy.MakeVertex(30, 0, 0)
V4 = geompy.MakeVertex(0, -3, 0)
V5 = geompy.MakeVertex(13, -10, 0)
V6 = geompy.MakeVertex(25, 10, 0)
V7 = geompy.MakeVertex(30, 5, 0)
BC1 = geompy.MakeBezier([ O, V1, V2, V3], False, "BC1")
BC2 = geompy.MakeBezier([V4, V5, V6, V7], False, "BC2")
pcalc = geompy.ShapeProximity()
pcalc.setShapes(BC1, BC2)
p_coarse = pcalc.coarseProximity()
p_fine = pcalc.preciseProximity()
assert(math.fabs(p_coarse - 7.3126564) < 1.e-7)
assert(math.fabs(p_fine - 7.380468495) < 1.e-7)
# Case 3: 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.99998769) < 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,87 @@
# 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)
# Case 1: cylinder and sphere (different coarse and fine proximities)
OCyl = geompy.MakeVertex(0, -5, 15)
Cyl = geompy.MakeCylinder(OCyl, OY, 3, 10, "Cyl")
AX1 = geompy.MakeTranslation(OX, 0, 0, 15, "AX1")
geompy.Rotate(Cyl, AX1, -20.0*math.pi/180.0)
Cyl_face = geompy.SubShapeAllSortedCentres(Cyl, geompy.ShapeType["FACE"], "Face")[1]
Sph = geompy.MakeSphereR(10, "Sph")
Box_1 = geompy.MakeBoxDXDYDZ(40, 40, 27.071067)
Translation_1 = geompy.MakeTranslation(Box_1, -20, -20, -20)
Cut_1 = geompy.MakeCutList(Sph, [Translation_1], True, "Cut_1")
Sph_face = geompy.SubShapeAllSortedCentres(Cut_1, geompy.ShapeType["FACE"], "Face")[1]
pcalc = geompy.ShapeProximity()
#pcalc.setShapes(Cyl_face, Sph_face)
pcalc.setShapes(Sph_face, Cyl_face)
p_coarse = pcalc.coarseProximity()
p_fine = pcalc.preciseProximity()
assert(math.fabs(p_coarse - 9.8649933) < 1.e-7)
assert(math.fabs(p_fine - 7.6984631) < 1.e-7)
geompy.MakeVertex(0, 2.63303, 17.2342, "p1")
geompy.MakeVertex(0, 0, 10, "p2")
print("With sampling 0: coarse = {} ; fine = {}".format(p_coarse, p_fine))
pcalc.setSampling(Cyl_face, 100) # number of sample points for the first shape
pcalc.setSampling(Sph_face, 100) # number of sample points for the second shape
p_coarse = pcalc.coarseProximity()
p_fine = pcalc.preciseProximity()
print("With sampling 100: coarse = {} ; fine = {}".format(p_coarse, p_fine))
pcalc.setSampling(Cyl_face, 1000) # number of sample points for the first shape
pcalc.setSampling(Sph_face, 1000) # number of sample points for the second shape
p_coarse = pcalc.coarseProximity()
p_fine = pcalc.preciseProximity()
print("With sampling 1000: coarse = {} ; fine = {}".format(p_coarse, p_fine))
# Case 2: 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")
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, "Translation_1")
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)
assert(math.fabs(proximity2_fine - 127.1141386) < 1.e-7)
geompy.MakeVertex(0, 0, 300, "p3")
geompy.MakeVertex(-63.2456, 0, 189.737, "p4")

View File

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