# 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()
#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>
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)
{
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,