From 4cf5812a679521a4cc05940918a9de13cac1db17 Mon Sep 17 00:00:00 2001 From: jgv Date: Wed, 14 Sep 2022 21:39:42 +0300 Subject: [PATCH] Fix of the bug --- src/GEOMImpl/GEOMImpl_IProximity.hxx | 24 +++ .../GEOMImpl_ShapeProximityDriver.cxx | 145 +++++++++++++++++- 2 files changed, 162 insertions(+), 7 deletions(-) diff --git a/src/GEOMImpl/GEOMImpl_IProximity.hxx b/src/GEOMImpl/GEOMImpl_IProximity.hxx index 48b0854e8..c32a5fdb7 100644 --- a/src/GEOMImpl/GEOMImpl_IProximity.hxx +++ b/src/GEOMImpl/GEOMImpl_IProximity.hxx @@ -26,6 +26,8 @@ #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 { @@ -61,12 +63,24 @@ public: 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); @@ -87,12 +101,22 @@ private: _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; }; diff --git a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx index c8cd2e459..99a743108 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx @@ -30,7 +30,9 @@ #include #include #include +#include #include +#include #include #include @@ -138,6 +140,60 @@ namespace { 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) { @@ -253,6 +309,8 @@ Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook 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"); @@ -262,26 +320,99 @@ Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook TopAbs_ShapeEnum aType1 = aShape1.ShapeType(); TopAbs_ShapeEnum aType2 = aShape2.ShapeType(); - gp_Pnt aP1, aP2; - aProximity.GetProximityPoints(aP1, aP2); + 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; + Standard_Real anExactValue = -1; if (aType1 == TopAbs_EDGE) { if (aType2 == TopAbs_EDGE) - aValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aP1, aP2); + { + if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aPnt1, aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER) + { + anExactValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1); + } + } else if (aType2 == TopAbs_FACE) - aValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aP1, aP2); + { + if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER) + { + anExactValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1); + } + } } else if (aType1 == TopAbs_FACE) { if (aType2 == TopAbs_EDGE) - aValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aP2, aP1); + { + if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aPnt2, aPnt1); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER) + { + anExactValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1); + } + } else if (aType2 == TopAbs_FACE) - aValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aP1, aP2); + { + if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE) + { + anExactValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2); + } + else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE && + aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER) + { + anExactValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1); + } + } } + if (anExactValue != -1) + aValue = anExactValue; + if (aValue >= 0) - aProximity.SetProximityPoints(aP1, aP2); + aProximity.SetProximityPoints(aPnt1, aPnt2); else Standard_ConstructionError::Raise("Failed to compute precise proximity"); } -- 2.39.2