]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeProximityDriver.cxx
Salome HOME
[GITHUB #1] updated TUI command doc for make sphere from point and radius
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeProximityDriver.cxx
1 // Copyright (C) 2022-2024  CEA, EDF, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <GEOMImpl_ShapeProximityDriver.hxx>
21 #include <GEOMImpl_IProximity.hxx>
22 #include <GEOMImpl_Types.hxx>
23
24 #include <GEOMUtils.hxx>
25
26 #include <BRep_Tool.hxx>
27 #include <BRepAdaptor_Curve.hxx>
28 #include <BRepAdaptor_Surface.hxx>
29 #include <BRepExtrema_ShapeProximity.hxx>
30 #include <BRepMesh_IncrementalMesh.hxx>
31 #include <Extrema_ExtPC.hxx>
32 #include <Extrema_ExtPS.hxx>
33 #include <Extrema_GenLocateExtCS.hxx>
34 #include <Extrema_GenLocateExtSS.hxx>
35 #include <Extrema_GenLocateExtPS.hxx>
36 #include <Extrema_LocateExtCC.hxx>
37 #include <Extrema_LocateExtPC.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS.hxx>
40
41 namespace {
42   static Standard_Real paramOnCurve(const BRepAdaptor_Curve& theCurve, const gp_Pnt& thePoint, const Standard_Real theTol)
43   {
44     Extrema_ExtPC aParamSearch(thePoint, theCurve, theCurve.FirstParameter(), theCurve.LastParameter());
45     if (aParamSearch.IsDone())
46     {
47       Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
48       Standard_Real aSqDistMin = RealLast();
49       for (Standard_Integer i = 1; i <= aNbExt; ++i)
50       {
51         if (aParamSearch.SquareDistance(i) < aSqDistMin)
52         {
53           anIndMin = i;
54           aSqDistMin = aParamSearch.SquareDistance(i);
55         }
56       }
57       if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
58       {
59         return aParamSearch.Point(anIndMin).Parameter();
60       }
61     }
62     return 0.5 * (theCurve.FirstParameter() + theCurve.LastParameter());
63   }
64
65   static void paramsOnSurf(const BRepAdaptor_Surface& theSurf, const gp_Pnt& thePoint, const Standard_Real theTol,
66                            Standard_Real& theU, Standard_Real& theV)
67   {
68     Extrema_ExtPS aParamSearch(thePoint, theSurf, Precision::PConfusion(), Precision::PConfusion());
69     if (aParamSearch.IsDone())
70     {
71       Standard_Integer anIndMin = 0, aNbExt = aParamSearch.NbExt();
72       Standard_Real aSqDistMin = RealLast();
73       for (Standard_Integer i = 1; i <= aNbExt; ++i)
74       {
75         if (aParamSearch.SquareDistance(i) < aSqDistMin)
76         {
77           anIndMin = i;
78           aSqDistMin = aParamSearch.SquareDistance(i);
79         }
80       }
81       if (anIndMin != 0 && aSqDistMin <= theTol * theTol)
82       {
83         return aParamSearch.Point(anIndMin).Parameter(theU, theV);
84       }
85     }
86     theU = 0.5 * (theSurf.FirstUParameter() + theSurf.LastUParameter());
87     theV = 0.5 * (theSurf.FirstVParameter() + theSurf.LastVParameter());
88   }
89
90   static Standard_Real extremaEE(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2,
91                                  gp_Pnt& thePoint1, gp_Pnt& thePoint2)
92   {
93     BRepAdaptor_Curve aCurve1(theEdge1);
94     BRepAdaptor_Curve aCurve2(theEdge2);
95
96     TopLoc_Location aLoc;
97     Standard_Real aTol1 = BRep_Tool::Tolerance(theEdge1);
98     Handle(Poly_Polygon3D) aPoly1 = BRep_Tool::Polygon3D (theEdge1, aLoc);
99     if (!aPoly1.IsNull())
100       aTol1 = Max (aTol1, aPoly1->Deflection());
101     Standard_Real aTol2 = BRep_Tool::Tolerance(theEdge2);
102     Handle(Poly_Polygon3D) aPoly2 = BRep_Tool::Polygon3D (theEdge2, aLoc);
103     if (!aPoly2.IsNull())
104       aTol2 = Max (aTol2, aPoly2->Deflection());
105   
106     Standard_Real aU1 = paramOnCurve(aCurve1, thePoint1, 2*aTol1);
107     Standard_Real aU2 = paramOnCurve(aCurve2, thePoint2, 2*aTol2);
108
109     Standard_Real aValue = -1.0;
110     Extrema_LocateExtCC anExtr(aCurve1, aCurve2, aU1, aU2);
111     if (anExtr.IsDone())
112     {
113       aValue = Sqrt(anExtr.SquareDistance());
114
115       Extrema_POnCurv aP1, aP2;
116       anExtr.Point(aP1, aP2);
117       thePoint1 = aP1.Value();
118       thePoint2 = aP2.Value();
119     }
120     return aValue;
121   }
122
123   static Standard_Real extremaPE(const gp_Pnt&      thePoint,
124                                  const TopoDS_Edge& theEdge,
125                                  gp_Pnt&            thePointOnEdge)
126   {
127     BRepAdaptor_Curve aCurve (theEdge);
128     
129     TopLoc_Location aLoc;
130     Standard_Real aTol = BRep_Tool::Tolerance(theEdge);
131     Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D (theEdge, aLoc);
132     if (!aPoly.IsNull())
133       aTol = Max (aTol, aPoly->Deflection());
134     
135     Standard_Real aParam = paramOnCurve (aCurve, thePointOnEdge, 2*aTol);
136     
137     Standard_Real aValue = -1.0;
138     Extrema_LocateExtPC anExtr (thePoint, aCurve, aParam, Precision::PConfusion());
139     if (anExtr.IsDone())
140     {
141       aValue = Sqrt(anExtr.SquareDistance());
142       
143       Extrema_POnCurv aPointOnCurve = anExtr.Point();
144       thePointOnEdge = aPointOnCurve.Value();
145     }
146     return aValue;
147   }
148   
149   static Standard_Real extremaPF(const gp_Pnt&      thePoint,
150                                  const TopoDS_Face& theFace,
151                                  gp_Pnt&            thePointOnFace)
152   {
153     BRepAdaptor_Surface aSurf (theFace);
154     
155     TopLoc_Location aLoc;
156     Standard_Real aTol = BRep_Tool::Tolerance(theFace);
157     Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation (theFace, aLoc);
158     if (!aTria.IsNull())
159       aTol = Max (aTol, aTria->Deflection());
160     
161     Standard_Real aU, aV;
162     paramsOnSurf(aSurf, thePointOnFace, 2*aTol, aU, aV);
163     
164     Standard_Real aValue = -1.0;
165     Extrema_GenLocateExtPS anExtr (aSurf);
166     anExtr.Perform (thePoint, aU, aV);
167     if (anExtr.IsDone())
168     {
169       aValue = Sqrt(anExtr.SquareDistance());
170       
171       Extrema_POnSurf aPointOnSurf = anExtr.Point();
172       thePointOnFace = aPointOnSurf.Value();
173     }
174     return aValue;
175   }
176
177   static Standard_Real extremaEF(const TopoDS_Edge& theEdge, const TopoDS_Face& theFace,
178                                  gp_Pnt& thePonE, gp_Pnt& thePonF)
179   {
180     BRepAdaptor_Curve aCurve(theEdge);
181     BRepAdaptor_Surface aSurf(theFace);
182
183     TopLoc_Location aLoc;
184     Standard_Real aTolEdge = BRep_Tool::Tolerance(theEdge);
185     Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D (theEdge, aLoc);
186     if (!aPoly.IsNull())
187       aTolEdge = Max (aTolEdge, aPoly->Deflection());
188     Standard_Real aTolFace = BRep_Tool::Tolerance(theFace);
189     Handle(Poly_Triangulation) aTria = BRep_Tool::Triangulation (theFace, aLoc);
190     if (!aTria.IsNull())
191       aTolFace = Max (aTolFace, aTria->Deflection());
192   
193     Standard_Real aP = paramOnCurve(aCurve, thePonE, 2*aTolEdge);
194     Standard_Real aU, aV;
195     paramsOnSurf(aSurf, thePonF, 2*aTolFace, aU, aV);
196
197     Standard_Real aValue = -1.0;
198     Extrema_GenLocateExtCS anExtr(aCurve, aSurf, aP, aU, aV, Precision::PConfusion(), Precision::PConfusion());
199     if (anExtr.IsDone())
200     {
201       aValue = Sqrt(anExtr.SquareDistance());
202       thePonE = anExtr.PointOnCurve().Value();
203       thePonF = anExtr.PointOnSurface().Value();
204     }
205     return aValue;
206   }
207
208   static Standard_Real extremaFF(const TopoDS_Face& theFace1, const TopoDS_Face& theFace2,
209                                  gp_Pnt& thePoint1, gp_Pnt& thePoint2)
210   {
211     BRepAdaptor_Surface aSurf1(theFace1);
212     BRepAdaptor_Surface aSurf2(theFace2);
213
214     TopLoc_Location aLoc;
215     Standard_Real aTol1 = BRep_Tool::Tolerance(theFace1);
216     Handle(Poly_Triangulation) aTria1 = BRep_Tool::Triangulation (theFace1, aLoc);
217     if (!aTria1.IsNull())
218       aTol1 = Max (aTol1, aTria1->Deflection());
219     Standard_Real aTol2 = BRep_Tool::Tolerance(theFace2);
220     Handle(Poly_Triangulation) aTria2 = BRep_Tool::Triangulation (theFace2, aLoc);
221     if (!aTria2.IsNull())
222       aTol2 = Max (aTol2, aTria2->Deflection());
223   
224     Standard_Real aU1, aV1;
225     paramsOnSurf(aSurf1, thePoint1, 2*aTol1, aU1, aV1);
226     Standard_Real aU2, aV2;
227     paramsOnSurf(aSurf2, thePoint2, 2*aTol2, aU2, aV2);
228
229     Standard_Real aValue = -1.0;
230     Extrema_GenLocateExtSS anExtr(aSurf1, aSurf2, aU1, aV1, aU2, aV2, Precision::PConfusion(), Precision::PConfusion());
231     if (anExtr.IsDone())
232     {
233       aValue = Sqrt(anExtr.SquareDistance());
234       thePoint1 = anExtr.PointOnS1().Value();
235       thePoint2 = anExtr.PointOnS2().Value();
236     }
237     return aValue;
238   }
239 }
240
241 //=======================================================================
242 //function : GetID
243 //purpose  :
244 //=======================================================================
245 const Standard_GUID& GEOMImpl_ShapeProximityDriver::GetID()
246 {
247   static Standard_GUID aShapeProximityDriver("1C3449A6-E4EB-407D-B623-89261C4BA785");
248   return aShapeProximityDriver;
249 }
250
251 //=======================================================================
252 //function : Execute
253 //purpose  :
254 //=======================================================================
255 Standard_Integer GEOMImpl_ShapeProximityDriver::Execute(Handle(TFunction_Logbook)& log) const
256 {
257   if (Label().IsNull())
258     return 0;
259
260   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
261   GEOMImpl_IProximity aProximity (aFunction);
262
263   Handle(GEOM_Function) aShapeFunc1, aShapeFunc2;
264   aProximity.GetShapes(aShapeFunc1, aShapeFunc2);
265   if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull())
266     return 0;
267
268   TopoDS_Shape aShape1 = aShapeFunc1->GetValue();
269   TopoDS_Shape aShape2 = aShapeFunc2->GetValue();
270
271   Standard_Real aValue = -1.0;
272
273   if (aFunction->GetType() == PROXIMITY_COARSE)
274   {
275     // tessellate shapes if there is no mesh exists
276     GEOMUtils::MeshShape(aShape1, 0.1, /*theForced*/false, 0.5, /*isRelative*/false);
277     GEOMUtils::MeshShape(aShape2, 0.1, /*theForced*/false, 0.5, /*isRelative*/false);
278
279     // compute proximity basing on the tessellation
280     BRepExtrema_ShapeProximity aCalcProx;
281     aCalcProx.LoadShape1(aShape1);
282     aCalcProx.LoadShape2(aShape2);
283     aCalcProx.SetNbSamples1(aProximity.GetNbSamples(PROXIMITY_ARG_SAMPLES1));
284     aCalcProx.SetNbSamples2(aProximity.GetNbSamples(PROXIMITY_ARG_SAMPLES2));
285     aCalcProx.Perform();
286
287     if (aCalcProx.IsDone())
288     {
289       aValue = aCalcProx.Proximity();
290       aProximity.SetProximityPoints(aCalcProx.ProximityPoint1(),
291                                     aCalcProx.ProximityPoint2());
292       aProximity.SetStatusOfPoints((Standard_Integer)aCalcProx.ProxPntStatus1(),
293                                    (Standard_Integer)aCalcProx.ProxPntStatus2());
294     }
295     else
296       Standard_ConstructionError::Raise("Failed to compute coarse proximity");
297   }
298   else if (aFunction->GetType() == PROXIMITY_PRECISE)
299   {
300     // coarse proximity value
301     // in some cases this value cannot be precised
302     // it can be precised only if at least one point is in the middle of the shape
303     aValue = aProximity.GetValue();
304
305     TopAbs_ShapeEnum aType1 = aShape1.ShapeType();
306     TopAbs_ShapeEnum aType2 = aShape2.ShapeType();
307
308     gp_Pnt aPnt1, aPnt2;
309     BRepExtrema_ProximityDistTool::ProxPnt_Status aStatus1, aStatus2;
310     Standard_Integer intStatus1, intStatus2;
311     aProximity.GetProximityPoints(aPnt1, aPnt2);
312     aProximity.GetStatusOfPoints(intStatus1, intStatus2);
313     aStatus1 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus1;
314     aStatus2 = (BRepExtrema_ProximityDistTool::ProxPnt_Status)intStatus2;
315
316     if (aType1 == TopAbs_EDGE)
317     {
318       if (aType2 == TopAbs_EDGE)
319       {
320         if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
321             aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
322         {
323           aValue = extremaEE(TopoDS::Edge(aShape1), TopoDS::Edge(aShape2), aPnt1, aPnt2);
324         }
325         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
326                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
327         {
328           aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
329         }
330         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
331                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
332         {
333           aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
334         }
335       }
336       else if (aType2 == TopAbs_FACE)
337       {
338         if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
339             aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
340         {
341           aValue = extremaEF(TopoDS::Edge(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
342         }
343         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
344                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
345         {
346           aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
347         }
348         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
349                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
350         {
351           aValue = extremaPE(aPnt2, TopoDS::Edge(aShape1), aPnt1);
352         }
353       }
354     }
355     else if (aType1 == TopAbs_FACE)
356     {
357       if (aType2 == TopAbs_EDGE)
358       {
359         if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
360             aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
361         {
362           aValue = extremaEF(TopoDS::Edge(aShape2), TopoDS::Face(aShape1), aPnt2, aPnt1);
363         }
364         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
365                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
366         {
367           aValue = extremaPE(aPnt1, TopoDS::Edge(aShape2), aPnt2);
368         }
369         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
370                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
371         {
372           aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
373         }
374       }
375       else if (aType2 == TopAbs_FACE)
376       {
377         if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
378             aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
379         {
380           aValue = extremaFF(TopoDS::Face(aShape1), TopoDS::Face(aShape2), aPnt1, aPnt2);
381         }
382         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER &&
383                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE)
384         {
385           aValue = extremaPF(aPnt1, TopoDS::Face(aShape2), aPnt2);
386         }
387         else if (aStatus1 == BRepExtrema_ProximityDistTool::ProxPnt_Status_MIDDLE &&
388                  aStatus2 == BRepExtrema_ProximityDistTool::ProxPnt_Status_BORDER)
389         {
390           aValue = extremaPF(aPnt2, TopoDS::Face(aShape1), aPnt1);
391         }
392       }
393     }
394
395     if (aValue >= 0)
396       aProximity.SetProximityPoints(aPnt1, aPnt2);
397     else
398       Standard_ConstructionError::Raise("Failed to compute precise proximity");
399   }
400   else
401   {
402     Standard_ConstructionError::Raise("incorrect algorithm");
403   }
404
405   aProximity.SetValue(aValue);
406   log->SetTouched(Label());
407   return 1;
408 }
409
410 //=======================================================================
411 //function : GetCreationInformation
412 //purpose  : Returns a name of creation operation and names and values of creation parameters
413 //=======================================================================
414 bool GEOMImpl_ShapeProximityDriver::GetCreationInformation(
415     std::string&             theOperationName,
416     std::vector<GEOM_Param>& theParams)
417 {
418   if (Label().IsNull())
419     return false;
420
421   Handle(GEOM_Function) aFunc = GEOM_Function::GetFunction(Label());
422   GEOMImpl_IProximity aProxFunc(aFunc);
423   Handle(GEOM_Function) aShape1, aShape2;
424   aProxFunc.GetShapes(aShape1, aShape2);
425
426   if (aFunc->GetType() == PROXIMITY_COARSE)
427     theOperationName = "PROXIMITY_COARSE";
428   else if (aFunc->GetType() == PROXIMITY_PRECISE)
429     theOperationName = "PROXIMITY_PRECISE";
430
431   AddParam(theParams, "Shape1", aShape1);
432   AddParam(theParams, "Shape2", aShape2);
433
434   return false;
435 }
436
437 IMPLEMENT_STANDARD_RTTIEXT(GEOMImpl_ShapeProximityDriver, GEOM_BaseDriver)