+ 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)
+{
+ BRepExtrema_DistShapeShape aDist = getExtemaDistShape(theShape1, theShape2);
+ return aDist.IsDone() ? aDist.Value() : Precision::Infinite();
+}
+
+double GeomAlgoAPI_ShapeTools::minimalDistance(const GeomShapePtr& theShape1,
+ const GeomShapePtr& theShape2,
+ std::array<double, 3> & fromShape1To2)
+{
+ BRepExtrema_DistShapeShape aDist = getExtemaDistShape(theShape1, theShape2);
+ const auto & pt1 = aDist.PointOnShape1(1);
+ const auto & pt2 = aDist.PointOnShape2(1) ;
+ fromShape1To2[0] = pt2.X() - pt1.X();
+ fromShape1To2[1] = pt2.Y() - pt1.Y();
+ fromShape1To2[2] = pt2.Z() - pt1.Z();