mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2024-11-11 16:19:17 +05:00
bos #29468: Advanced geometry features: distance Edge-Edge & Face-Face
This commit is contained in:
parent
901ba4f298
commit
9f73090059
40
doc/salome/examples/shape_proximity.py
Normal file
40
doc/salome/examples/shape_proximity.py
Normal 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)
|
@ -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
|
||||
)
|
||||
|
BIN
doc/salome/gui/GEOM/images/Shape_proximity_0.png
Normal file
BIN
doc/salome/gui/GEOM/images/Shape_proximity_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
BIN
doc/salome/gui/GEOM/images/Shape_proximity_1.png
Normal file
BIN
doc/salome/gui/GEOM/images/Shape_proximity_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
52
doc/salome/gui/GEOM/input/shape_proximity.doc
Normal file
52
doc/salome/gui/GEOM/input/shape_proximity.doc
Normal 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".
|
||||
|
||||
*/
|
@ -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>
|
||||
|
||||
*/
|
||||
|
6
doc/salome/gui/GEOM/input/tui_shape_proximity.doc
Normal file
6
doc/salome/gui/GEOM/input/tui_shape_proximity.doc
Normal file
@ -0,0 +1,6 @@
|
||||
/*!
|
||||
|
||||
\page tui_shape_proximity_page Compute Proximity between Shapes
|
||||
\tui_script{shape_proximity.py}
|
||||
|
||||
*/
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
122
src/GEOMImpl/GEOMImpl_IProximity.hxx
Normal file
122
src/GEOMImpl/GEOMImpl_IProximity.hxx
Normal 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;
|
||||
};
|
457
src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx
Normal file
457
src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx
Normal 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)
|
45
src/GEOMImpl/GEOMImpl_ShapeProximityDriver.hxx
Normal file
45
src/GEOMImpl/GEOMImpl_ShapeProximityDriver.hxx
Normal 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
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(); }
|
||||
|
||||
|
@ -73,6 +73,7 @@ SET(_python_SCRIPTS
|
||||
gsketcher.py
|
||||
canonicalrecognition.py
|
||||
conformity.py
|
||||
proximity.py
|
||||
)
|
||||
|
||||
# Advanced scripts
|
||||
|
@ -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
|
||||
## @}
|
||||
|
||||
|
91
src/GEOM_SWIG/proximity.py
Normal file
91
src/GEOM_SWIG/proximity.py
Normal 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
|
130
test/test_proximity_edge_edge.py
Normal file
130
test/test_proximity_edge_edge.py
Normal 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)
|
87
test/test_proximity_face_face.py
Normal file
87
test/test_proximity_face_face.py
Normal 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")
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user