Salome HOME
[bos #29468] [EDF] (2022-T1) Advanced geometry features: distance Edge-Edge & Face...
authorjfa <jfa@opencascade.com>
Fri, 17 Jun 2022 15:03:59 +0000 (18:03 +0300)
committerGérald NICOLAS <gerald.nicolas@edf.fr>
Tue, 11 Apr 2023 13:28:12 +0000 (15:28 +0200)
src/FeaturesAPI/FeaturesAPI_Measurement.cpp
src/FeaturesAPI/FeaturesAPI_Measurement.h
src/FeaturesPlugin/FeaturesPlugin_Measurement.cpp
src/FeaturesPlugin/FeaturesPlugin_Measurement.h
src/FeaturesPlugin/Test/TestMeasurementDistance.py
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h
src/PythonAPI/model/features/__init__.py

index 6954951cba2e215027f6546667be3b9936890ec5..4230b69d4777fa82e0aebc75793fddcc62455435 100644 (file)
@@ -139,3 +139,28 @@ double measureAngle(const std::shared_ptr<ModelAPI_Document>& thePart,
 
   return aValue;
 }
+
+double shapeProximity(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const ModelHighAPI_Selection& theFrom,
+                      const ModelHighAPI_Selection& theTo)
+{
+  FeaturePtr aMeasure = thePart->addFeature(FeaturesPlugin_Measurement::ID());
+  fillAttribute(FeaturesPlugin_Measurement::MEASURE_PROXIMITY(),
+                aMeasure->string(FeaturesPlugin_Measurement::MEASURE_KIND()));
+  fillAttribute(theFrom,
+                aMeasure->selection(FeaturesPlugin_Measurement::DISTANCE_FROM_OBJECT_ID()));
+  fillAttribute(theTo,
+                aMeasure->selection(FeaturesPlugin_Measurement::DISTANCE_TO_OBJECT_ID()));
+  aMeasure->execute();
+
+  // obtain result
+  AttributeDoubleArrayPtr aResult = std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
+      aMeasure->attribute(FeaturesPlugin_Measurement::RESULT_VALUES_ID()));
+  double aValue = aResult->size() ? aResult->value(0) : -1.0;
+
+  // perform removing macro feature Measurement
+  thePart->removeFeature(aMeasure);
+  apply();
+
+  return aValue;
+}
index 937bece21411684f44cea3c79700d54d41402201..715dc12b2f9006618b12d0d713c3415e005b6bda 100644 (file)
@@ -62,4 +62,11 @@ double measureAngle(const std::shared_ptr<ModelAPI_Document>& thePart,
                     const ModelHighAPI_Selection& thePoint2,
                     const ModelHighAPI_Selection& thePoint3);
 
+/// \ingroup CPPHighAPI
+/// \brief Calculate maximum of all distances between objects.
+FEATURESAPI_EXPORT
+double shapeProximity(const std::shared_ptr<ModelAPI_Document>& thePart,
+                      const ModelHighAPI_Selection& theFrom,
+                      const ModelHighAPI_Selection& theTo);
+
 #endif // FeaturesAPI_Measurement_H_
index 7e497ada8245e6ee7a84fdafbf882baec20ae520..d3f0a9db208b9c3e64eac0f7eccaa8d0d9fd16d4 100644 (file)
@@ -93,12 +93,15 @@ void FeaturesPlugin_Measurement::attributeChanged(const std::string& theID)
     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
       attribute(RESULT_VALUES_ID()))->setSize(0);
   }
-  if (theID != RESULT_ID()) {
+  else if (theID != RESULT_ID() &&
+           theID != RESULT_VALUES_ID()) {
     std::string aKind = string(MEASURE_KIND())->value();
     if (aKind == MEASURE_LENGTH())
       computeLength();
     else if (aKind == MEASURE_DISTANCE())
       computeDistance();
+    else if (aKind == MEASURE_PROXIMITY())
+      computeProximity();
     else if (aKind == MEASURE_RADIUS())
       computeRadius();
     else if (aKind == MEASURE_ANGLE())
@@ -184,6 +187,41 @@ void FeaturesPlugin_Measurement::computeDistance()
   aValues->setValue(0, aDistance);
 }
 
+void FeaturesPlugin_Measurement::computeProximity()
+{
+  AttributeSelectionPtr aFirstFeature = selection(DISTANCE_FROM_OBJECT_ID());
+  GeomShapePtr aShape1;
+  if (aFirstFeature && aFirstFeature->isInitialized()) {
+    aShape1 = aFirstFeature->value();
+    if (!aShape1 && aFirstFeature->context())
+      aShape1 = aFirstFeature->context()->shape();
+  }
+
+  AttributeSelectionPtr aSecondFeature = selection(DISTANCE_TO_OBJECT_ID());
+  GeomShapePtr aShape2;
+  if (aSecondFeature && aSecondFeature->isInitialized()) {
+    aShape2 = aSecondFeature->value();
+    if (!aShape2 && aSecondFeature->context())
+      aShape2 = aSecondFeature->context()->shape();
+  }
+
+  if (!aShape1 || !aShape2) {
+    string(RESULT_ID())->setValue("");
+    return;
+  }
+
+  double aDistance = GeomAlgoAPI_ShapeTools::shapeProximity(aShape1, aShape2);
+
+  std::ostringstream anOutput;
+  anOutput << "Proximity = " << std::setprecision(10) << aDistance;
+  string(RESULT_ID())->setValue(anOutput.str());
+
+  AttributeDoubleArrayPtr aValues =
+      std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
+  aValues->setSize(1);
+  aValues->setValue(0, aDistance);
+}
+
 void FeaturesPlugin_Measurement::computeRadius()
 {
   AttributeSelectionPtr aSelectedFeature = selection(CIRCULAR_OBJECT_ID());
index 5ef1a1c0896e6fbabfb2a8418d24f6a782cf5f89..e4fdc1d6c30d8f61e526d4ae6e06a5f9eb5fb4a5 100644 (file)
@@ -74,6 +74,13 @@ public:
     return MY_MEASURE_ID;
   }
 
+  /// Attribute name for distance measure.
+  inline static const std::string& MEASURE_PROXIMITY()
+  {
+    static const std::string MY_MEASURE_ID("Proximity");
+    return MY_MEASURE_ID;
+  }
+
   /// Attribute name for radius measure.
   inline static const std::string& MEASURE_RADIUS()
   {
@@ -211,6 +218,8 @@ private:
   void computeLength();
   /// Compute minimal distance between pair of shapes
   void computeDistance();
+  /// Compute proximity (maximum of all minimal distances between pair of shapes)
+  void computeProximity();
   /// Compute radius of circular edge, cylindrical surface or sphere.
   void computeRadius();
   /// Compute angle(s) between pair of edges if they are intersected
index 4afc8d830d6c11e4a08fe751049f79140b949fa0..d950dcd09608afc090363aa370119f5788642c4e 100644 (file)
@@ -87,44 +87,59 @@ TOLERANCE = 1.e-6
 # reference data
 REF_DATA = [(model.selection("VERTEX", "PartSet/Origin"),
              model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"),
-             122.4744871),
+             122.4744871,
+             "NA"),
             (model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"),
              model.selection("VERTEX", "Sketch_2/SketchArc_1"),
-             36.94403089),
+             36.94403089,
+             "NA"),
             (model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face]"),
              model.selection("EDGE", "([Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face])([Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face])([Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face])([Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face])"),
-             0),
+             0,
+             100.0),
             (model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face]"),
              model.selection("EDGE", "[Extrusion_2_1/Generated_Face&Sketch_2/SketchArc_1_2][Extrusion_2_1/To_Face]"),
-             16.00781059),
+             16.00781059,
+             176.710217655),
             (model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face]"),
              model.selection("FACE", "Extrusion_2_1/Generated_Face&Sketch_2/SketchArc_1_2"),
-             8.412291828),
+             8.412291828,
+             "NA"),
             (model.selection("VERTEX", "Sketch_1/SketchCircle_1_2__cc"),
              model.selection("FACE", "Plane_1"),
-             35.35533906),
+             35.35533906,
+             "NA"),
             (model.selection("FACE", "Extrusion_2_2/From_Face"),
              model.selection("FACE", "Extrusion_2_2/To_Face"),
+             100,
              100),
             (model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2"),
              model.selection("FACE", "Extrusion_2_1/Generated_Face&Sketch_2/SketchArc_1_2"),
-             0),
-            (model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2"),
-             model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_5"),
-             27.63932023),
+             0,
+             165.799606),
+            (model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_5"),
+             model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2"),
+             27.63932023,
+             40.0),
             (model.selection("SOLID", "Extrusion_1_1"),
              model.selection("FACE", "Extrusion_2_1/To_Face"),
-             12.5),
+             12.5,
+             "NA"),
             (model.selection("SOLID", "Extrusion_1_1"),
              model.selection("SOLID", "Extrusion_2_1"),
-             0),
+             0,
+             "NA"),
             (model.selection("SOLID", "Extrusion_1_1"),
              model.selection("SOLID", "Extrusion_2_2"),
-             87.5)
+             87.5,
+             "NA")
            ]
 
 for ref in REF_DATA:
     dist = model.measureDistance(Part_1_doc, ref[0], ref[1])
     assert(math.fabs(dist - ref[2]) < TOLERANCE), "Distance {} differs from expected value {}".format(dist, ref[2])
+    if ref[3] != "NA":
+        prox = model.shapeProximity(Part_1_doc, ref[0], ref[1])
+        assert(math.fabs(prox - ref[3]) < TOLERANCE), "Proximity {} differs from expected value {}".format(prox, ref[3])
 
 model.end()
index d4996e38ba9eedc6bd07dcaf75dfc9c62bd3257b..1a10fc35390f651ba9e8fe7e00340213e0cbb1ad 100644 (file)
@@ -50,7 +50,9 @@
 #include <BRepCheck_Analyzer.hxx>
 #include <BRepExtrema_DistShapeShape.hxx>
 #include <BRepExtrema_ExtCF.hxx>
+#include <BRepExtrema_ShapeProximity.hxx>
 #include <BRepGProp.hxx>
+#include <BRepMesh_IncrementalMesh.hxx>
 #include <BRepTools.hxx>
 #include <BRepTools_WireExplorer.hxx>
 #include <BRepTopAdaptor_FClass2d.hxx>
 
 #include <BOPAlgo_Builder.hxx>
 
+#include <Extrema_GenLocateExtCS.hxx>
+#include <Extrema_GenLocateExtSS.hxx>
+#include <Extrema_GenLocateExtPS.hxx>
+#include <Extrema_LocateExtCC.hxx>
+#include <Extrema_LocateExtPC.hxx>
+
 #include <Geom2d_Curve.hxx>
 #include <Geom2d_Curve.hxx>
 
@@ -340,8 +348,185 @@ auto getExtemaDistShape = [](const GeomShapePtr& theShape1,
   aDist.Perform();
   return aDist;
 };
+
+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,
+                               const gp_Pnt&      thePoint1,
+                               const gp_Pnt&      thePoint2)
+{
+  BRepAdaptor_Curve aCurve1(theEdge1);
+  BRepAdaptor_Curve aCurve2(theEdge2);
+
+  Standard_Real aU1 = paramOnCurve(aCurve1, thePoint1, BRep_Tool::Tolerance(theEdge1));
+  Standard_Real aU2 = paramOnCurve(aCurve2, thePoint2, BRep_Tool::Tolerance(theEdge2));
+
+  Standard_Real aValue = -1.0;
+  Extrema_LocateExtCC anExtr(aCurve1, aCurve2, aU1, aU2);
+  if (anExtr.IsDone() && aValue > Precision::Confusion())
+    aValue = Sqrt(anExtr.SquareDistance());
+  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,
+                               const gp_Pnt&      thePonE,
+                               const gp_Pnt&      thePonF)
+{
+  BRepAdaptor_Curve aCurve(theEdge);
+  BRepAdaptor_Surface aSurf(theFace);
+
+  Standard_Real aP = paramOnCurve(aCurve, thePonE, BRep_Tool::Tolerance(theEdge));
+  Standard_Real aU, aV;
+  paramsOnSurf(aSurf, thePonF, BRep_Tool::Tolerance(theFace), aU, aV);
+
+  Standard_Real aValue = -1.0;
+  Extrema_GenLocateExtCS anExtr(aCurve, aSurf, aP, aU, aV, Precision::PConfusion(), Precision::PConfusion());
+  if (anExtr.IsDone() && aValue > Precision::Confusion())
+    aValue = Sqrt(anExtr.SquareDistance());
+  return aValue;
 }
 
+static Standard_Real extremaFF(const TopoDS_Face& theFace1,
+                               const TopoDS_Face& theFace2,
+                               const gp_Pnt&      thePoint1,
+                               const gp_Pnt&      thePoint2)
+{
+  BRepAdaptor_Surface aSurf1(theFace1);
+  BRepAdaptor_Surface aSurf2(theFace2);
+
+  Standard_Real aU1, aV1;
+  paramsOnSurf(aSurf1, thePoint1, BRep_Tool::Tolerance(theFace1), aU1, aV1);
+  Standard_Real aU2, aV2;
+  paramsOnSurf(aSurf2, thePoint2, BRep_Tool::Tolerance(theFace2), aU2, aV2);
+
+  Standard_Real aValue = -1.0;
+  Extrema_GenLocateExtSS anExtr(aSurf1, aSurf2, aU1, aV1, aU2, aV2, Precision::PConfusion(), Precision::PConfusion());
+  if (anExtr.IsDone() && aValue > Precision::Confusion())
+    aValue = Sqrt(anExtr.SquareDistance());
+  return aValue;
+}
+
+} // namespace
+
 double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
                                                const GeomShapePtr& theShape2)
 {
@@ -362,6 +547,123 @@ double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
   return aDist.IsDone() ? aDist.Value() : Precision::Infinite();
 }
 
+//==================================================================================================
+double GeomAlgoAPI_ShapeTools::shapeProximity(const GeomShapePtr& theShape1,
+                                              const GeomShapePtr& theShape2)
+{
+  double aResult = -1.0;
+  if (!theShape1.get() || !theShape2.get())
+    return aResult;
+
+  const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+  const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+  TopAbs_ShapeEnum aType1 = aShape1.ShapeType();
+  TopAbs_ShapeEnum aType2 = aShape2.ShapeType();
+
+  // tessellate shapes if there is no mesh exists
+  tessellateShape(aShape1);
+  tessellateShape(aShape2);
+
+  BRepExtrema_ShapeProximity aDist (aShape1, aShape2);
+  aDist.Perform();
+  if (aDist.IsDone()) {
+    aResult = aDist.Proximity();
+
+    // refine the result
+    gp_Pnt aPnt1 = aDist.ProximityPoint1();
+    gp_Pnt aPnt2 = aDist.ProximityPoint2();
+
+    BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus1 = aDist.ProxPntStatus1();
+    BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus2 = aDist.ProxPntStatus2();
+
+    double aValue = -1.0;
+
+    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.0)
+      aResult = aValue;
+  }
+  return aResult;
+}
+
 //==================================================================================================
 std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
   const std::shared_ptr<GeomAPI_Shape> theCompound,
index 3346fbe54cdd768bab7fb8f10af985cf21ddc52b..0c058e147472dcce39bd0b92716dc2fad1f4bf22 100644 (file)
@@ -88,6 +88,11 @@ public:
                                                    const GeomShapePtr& theShape2,
                                                    std::array<double, 3> & fromShape1To2);
 
+  /// \brief Calculate maximal value of all possible distances between shapes.
+  ///        The shapes can be two edges or two faces only.
+  GEOMALGOAPI_EXPORT static double shapeProximity(const GeomShapePtr& theShape1,
+                                                  const GeomShapePtr& theShape2);
+
   /// \brief Combines faces with common edges to shells, or solids to compsolids.
   /// \param[in] theCompound compound of shapes.
   /// \param[in] theType type of combine.
index 5cfa49f0e2999f21c595a4507b2d2d74d4dadb81..14351b736c287980b1e873af80b8fcb44bd6d582 100644 (file)
@@ -30,6 +30,7 @@ from FeaturesAPI import addRecover
 from FeaturesAPI import addFillet, addChamfer
 from FeaturesAPI import addFusionFaces
 from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle
+from FeaturesAPI import shapeProximity
 from FeaturesAPI import getPointCoordinates, getGeometryCalculation, getBoundingBox
 from FeaturesAPI import getNormal
 from FeaturesAPI import makeVertexInsideFace