0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / BRepExtrema / BRepExtrema_DistanceSS.cxx
1 // Created on: 1996-04-22
2 // Created by: Herve LOUESSARD 
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified: Sergey ZERCHANINOV
18
19 #include <BRepExtrema_DistanceSS.hxx>
20
21 #include <TopTools_IndexedMapOfShape.hxx>
22 #include <TopExp.hxx>
23 #include <gp_Pnt.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepExtrema_SupportType.hxx>
27 #include <Standard_Real.hxx>
28 #include <BRepExtrema_SolutionElem.hxx>
29 #include <BRepExtrema_SeqOfSolution.hxx>
30 #include <Standard_Boolean.hxx>
31 #include <Standard_Integer.hxx> 
32 #include <TopAbs_ShapeEnum.hxx>
33 #include <TopoDS.hxx>
34 #include <Bnd_Box.hxx>
35 #include <BRepExtrema_ExtPC.hxx>
36 #include <BRepExtrema_ExtPF.hxx>
37 #include <Extrema_ExtFlag.hxx>
38 #include <BRepExtrema_ExtCC.hxx>
39 #include <BRepExtrema_ExtCF.hxx>
40 #include <BRepExtrema_ExtFF.hxx>
41 #include <BRepClass_FaceClassifier.hxx>
42 #include <TopAbs.hxx>
43 #include <Geom_Curve.hxx>
44 #include <GeomAbs_Shape.hxx>
45 #include <GeomAdaptor_Curve.hxx>
46 #include <TColStd_Array1OfReal.hxx>
47 #include <BRepBuilderAPI_MakeVertex.hxx>
48 #include <BRepBuilderAPI_MakeEdge.hxx>
49 #include <BRepBuilderAPI_MakeFace.hxx>
50 #include <Geom_Surface.hxx>
51 #include <GeomAPI_ProjectPointOnSurf.hxx>
52 #include <GeomAPI_ProjectPointOnCurve.hxx>
53 #include <Geom_RectangularTrimmedSurface.hxx>
54 #include <Geom_TrimmedCurve.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepTools.hxx>
57 #include <TColgp_Array1OfPnt.hxx>
58
59
60 /*********************************************************************************/
61
62 //------------------------------------------------------------------------------
63 // function: TRI_SOLUTION
64 //------------------------------------------------------------------------------
65 static Standard_Boolean TRI_SOLUTION (const BRepExtrema_SeqOfSolution& SeqSol, const gp_Pnt& Pt)
66 {
67   const Standard_Integer Nbsol = SeqSol.Length();
68   for (Standard_Integer i = 1; i <= Nbsol; i++)
69   {
70     const Standard_Real dst = SeqSol.Value(i).Point().Distance(Pt);
71     if (dst <= Precision::Confusion()) return Standard_False;
72   }
73   return Standard_True;
74 }  
75
76 //------------------------------------------------------------------------------
77 // function: MIN_SOLUTION
78 //------------------------------------------------------------------------------
79 static void MIN_SOLUTION (const BRepExtrema_SeqOfSolution& SeqSol1,
80                           const BRepExtrema_SeqOfSolution& SeqSol2,
81                           const Standard_Real DstRef,
82                           const Standard_Real Eps,
83                           BRepExtrema_SeqOfSolution& seqSol1,
84                           BRepExtrema_SeqOfSolution& seqSol2)
85 {
86   const Standard_Integer nbSol = SeqSol1.Length();
87   for (Standard_Integer i = 1; i <= nbSol; i++)
88   {
89     const Standard_Real dst1 = SeqSol1.Value(i).Dist();
90     if (fabs(dst1 - DstRef) < Eps)
91         {         
92       seqSol1.Append(SeqSol1.Value(i));
93       seqSol2.Append(SeqSol2.Value(i));
94         }
95   }
96 }
97
98 //------------------------------------------------------------------------------
99 // function: TRIM_INFINIT_EDGE
100 //------------------------------------------------------------------------------
101 static void TRIM_INFINIT_EDGE(const TopoDS_Edge& S1, const TopoDS_Edge& S2, TopoDS_Edge& aResEdge,
102                               Standard_Boolean& bIsTrim1, Standard_Boolean& bIsTrim2)
103 {
104   if ( BRep_Tool::Degenerated(S1) || BRep_Tool::Degenerated(S2) )
105     return;
106
107   aResEdge = S2;
108   Standard_Real aFirst1, aLast1, aFirst2, aLast2;
109   Handle(Geom_Curve) pCurv1 = BRep_Tool::Curve(S1, aFirst1, aLast1);
110   Handle(Geom_Curve) pCurv2 = BRep_Tool::Curve(S2, aFirst2, aLast2);
111
112   if (Precision::IsInfinite(aFirst1) &&
113       Precision::IsInfinite(aLast1)  &&
114       Precision::IsInfinite(aFirst2) &&
115       Precision::IsInfinite(aLast2))
116     return;
117   
118   Standard_Real Umin = 0., Umax = 0.;
119   Standard_Boolean bUmin, bUmax;
120   bUmin = bUmax = Standard_False;
121
122   Handle(Geom_Curve) pCurv;
123   if ( !pCurv1.IsNull() && (Precision::IsInfinite(aFirst1) || Precision::IsInfinite(aLast1)) )
124   {
125     pCurv = pCurv1;
126     bIsTrim1 = Standard_True;
127     if (!Precision::IsInfinite(aFirst1))
128     {
129       bUmin = Standard_True;
130       Umin = aFirst1;
131     }
132     else if (!Precision::IsInfinite(aLast1))
133     {
134       bUmax = Standard_True;
135       Umax = aLast1;
136     }
137   }
138   else if ( !pCurv2.IsNull() && (Precision::IsInfinite(aFirst2) || Precision::IsInfinite(aLast2)) )
139   {
140     pCurv = pCurv2;
141     bIsTrim2 = Standard_True;
142     if (!Precision::IsInfinite(aFirst2))
143     {
144       bUmin = Standard_True;
145       Umin = aFirst2;
146     }
147     else if (!Precision::IsInfinite(aLast2))
148     {
149       bUmax = Standard_True;
150       Umax = aLast2;
151     }
152   }
153   if (bIsTrim1 || bIsTrim2)
154   {
155     Bnd_Box aEdgeBox;
156     if (bIsTrim1)
157       BRepBndLib::Add(S2, aEdgeBox);
158     if (bIsTrim2)
159       BRepBndLib::Add(S1, aEdgeBox);
160     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
161     aEdgeBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
162
163     const gp_Pnt aPnt0(Xmin, Ymin, Zmin);
164     const gp_Pnt aPnt1(Xmin, Ymax, Zmin);
165     const gp_Pnt aPnt2(Xmin, Ymax, Zmax);
166     const gp_Pnt aPnt3(Xmin, Ymin, Zmax);
167     const gp_Pnt aPnt4(Xmax, Ymax, Zmin);
168     const gp_Pnt aPnt5(Xmax, Ymax, Zmax);
169     const gp_Pnt aPnt6(Xmax, Ymin, Zmax);
170     const gp_Pnt aPnt7(Xmax, Ymin, Zmin);
171
172         Standard_Real arrU[8];
173     GeomAPI_ProjectPointOnCurve aProj(aPnt0, pCurv);
174     /*szv:aProj.Perform(aPnt0);*/ arrU[0] = aProj.LowerDistanceParameter();
175     aProj.Perform(aPnt1); arrU[1] = aProj.LowerDistanceParameter();
176     aProj.Perform(aPnt2); arrU[2] = aProj.LowerDistanceParameter();
177     aProj.Perform(aPnt3); arrU[3] = aProj.LowerDistanceParameter();
178     aProj.Perform(aPnt4); arrU[4] = aProj.LowerDistanceParameter();
179     aProj.Perform(aPnt5); arrU[5] = aProj.LowerDistanceParameter();
180     aProj.Perform(aPnt6); arrU[6] = aProj.LowerDistanceParameter();
181     aProj.Perform(aPnt7); arrU[7] = aProj.LowerDistanceParameter();
182     
183     if (!bUmin)
184       Umin = arrU[0];
185         
186     if (!bUmax)
187       Umax = arrU[0];
188
189     Standard_Integer i = 0;
190     while (i < 8)
191         {
192       const Standard_Real aU = arrU[i++];
193           if (aU < Umin)
194             Umin = aU;
195           else if (aU > Umax)
196             Umax = aU;
197         }
198
199     Standard_Real tol = Precision::Confusion();
200     if (bIsTrim1)
201       tol = BRep_Tool::Tolerance(S1);
202     else if (bIsTrim2)
203       tol = BRep_Tool::Tolerance(S2);
204
205     const Standard_Real EpsU = GeomAdaptor_Curve(pCurv).Resolution(3.*tol);
206     if (fabs(Umin - Umax) < EpsU)
207     {
208       Umin -= EpsU;
209       Umax += EpsU;
210     }
211
212     Handle(Geom_Curve) result = new Geom_TrimmedCurve(pCurv, Umin, Umax);
213     aResEdge = BRepBuilderAPI_MakeEdge(result);
214   }
215 }
216
217 //------------------------------------------------------------------------------
218 // function: TRIM_INFINIT_FACE
219 //------------------------------------------------------------------------------
220 static void TRIM_INFINIT_FACE(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
221                               TopoDS_Face& aResFace, Standard_Boolean& bIsInfinit)
222 {
223   bIsInfinit = Standard_False;
224
225   TopAbs_ShapeEnum Type1 = S1.ShapeType();     
226   TopAbs_ShapeEnum Type2 = S2.ShapeType();
227
228   TopoDS_Edge aE;
229   TopoDS_Face aF;
230   
231   if (Type1 == TopAbs_EDGE && Type2 == TopAbs_FACE)
232   {
233     aE = TopoDS::Edge(S1);
234     if ( BRep_Tool::Degenerated(aE) )
235       return;
236     aF = TopoDS::Face(S2);
237   }
238   else if (Type2 == TopAbs_EDGE && Type1 == TopAbs_FACE)
239   {
240     aE = TopoDS::Edge(S2);
241     if ( BRep_Tool::Degenerated(aE) )
242       return;
243     aF = TopoDS::Face(S1);
244   }
245   else
246   {
247     bIsInfinit = Standard_False;
248     return;
249   }
250
251   aResFace = aF;
252   Handle(Geom_Surface) pSurf = BRep_Tool::Surface(aF);
253  
254   const Standard_Boolean bRestrict = BRep_Tool::NaturalRestriction(aF);
255
256   Standard_Real U1, V1, U2, V2;
257   Standard_Real Umin = RealLast(), Umax = RealFirst(), Vmin = RealLast(), Vmax = RealFirst();
258   Standard_Boolean bUmin, bUmax, bVmin, bVmax;
259   bUmin = bUmax = bVmin = bVmax = Standard_False;
260   Standard_Boolean bIsTrim = Standard_False;
261
262   if (bRestrict)
263   {
264     pSurf->Bounds(U1, U2, V1, V2);
265     if (Precision::IsInfinite(U1))
266       bIsTrim = Standard_True;
267     else
268     {
269       Umin = U1;
270       bUmin = Standard_True;
271     }
272
273     if (Precision::IsInfinite(U2))
274       bIsTrim = Standard_True;
275     else
276     {
277       Umax = U2;
278       bUmax = Standard_True;
279     }
280
281     if (Precision::IsInfinite(V1))
282       bIsTrim = Standard_True;
283     else
284         {
285       Vmin = V1;
286       bVmin = Standard_True;
287         }
288       
289     if (Precision::IsInfinite(V2))
290       bIsTrim = Standard_True;
291     else
292         {
293       Vmax = V2;
294       bVmax = Standard_True;
295     }
296   }
297   else
298   {
299     BRepTools::UVBounds(aF, U1, U2, V1, V2);
300     if (Precision::IsInfinite(U1) &&
301         Precision::IsInfinite(U2) &&
302         Precision::IsInfinite(V1) &&
303         Precision::IsInfinite(V2))
304       bIsTrim = Standard_True;
305   }
306
307   if (bIsTrim)
308   {      
309     Bnd_Box aEdgeBox;
310     BRepBndLib::Add(aE, aEdgeBox);
311
312     if(aEdgeBox.IsWhole())
313       return;
314
315     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
316     aEdgeBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
317
318     const gp_Pnt aPnt0(Xmin, Ymin, Zmin);
319     const gp_Pnt aPnt1(Xmin, Ymax, Zmin);
320     const gp_Pnt aPnt2(Xmin, Ymax, Zmax);
321     const gp_Pnt aPnt3(Xmin, Ymin, Zmax);
322     const gp_Pnt aPnt4(Xmax, Ymax, Zmin);
323     const gp_Pnt aPnt5(Xmax, Ymax, Zmax);
324     const gp_Pnt aPnt6(Xmax, Ymin, Zmax);
325     const gp_Pnt aPnt7(Xmax, Ymin, Zmin);
326
327     Standard_Real arrU[8], arrV[8];
328     GeomAPI_ProjectPointOnSurf aProj(aPnt0, pSurf);
329     /*szv:aProj.Perform(aPnt0);*/ if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[0],arrV[0]);
330     aProj.Perform(aPnt1); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[1],arrV[1]);
331     aProj.Perform(aPnt2); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[2],arrV[2]);
332     aProj.Perform(aPnt3); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[3],arrV[3]);
333     aProj.Perform(aPnt4); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[4],arrV[4]);
334     aProj.Perform(aPnt5); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[5],arrV[5]);
335     aProj.Perform(aPnt6); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[6],arrV[6]);
336     aProj.Perform(aPnt7); if (aProj.IsDone()) aProj.LowerDistanceParameters(arrU[7],arrV[7]);
337
338     if (!bUmin)
339       Umin = arrU[0];
340     if (!bUmax)
341       Umax = arrU[0];
342     if (!bVmin)
343       Vmin = arrV[0];
344     if (!bVmax)
345       Vmax = arrV[0];
346
347     Standard_Integer i = 0;
348     while (i < 8)
349         {
350       const Standard_Real aU = arrU[i];
351           if (aU < Umin)
352             Umin = aU;
353           else if (aU > Umax)
354             Umax = aU;
355
356       const Standard_Real aV = arrV[i];
357           if (aV < Vmin)
358             Vmin = aV;
359           else if (aV > Vmax)
360             Vmax = aV;
361
362       i++;
363         }
364       
365     GeomAdaptor_Surface aGAS(pSurf);
366     const Standard_Real tol = BRep_Tool::Tolerance(aF);
367
368     const Standard_Real EpsU = aGAS.UResolution(3.*tol);
369     if (fabs(Umin - Umax) < EpsU)
370     {
371       Umin -= EpsU;
372       Umax += EpsU;
373     }
374
375     const Standard_Real EpsV = aGAS.VResolution(3.*tol);
376     if (fabs(Vmin - Vmax) < EpsV)
377     {
378       Vmin -= EpsV;
379       Vmax += EpsV;
380     }
381
382     Handle(Geom_Surface) result = new Geom_RectangularTrimmedSurface(pSurf, Umin, Umax, Vmin, Vmax);
383     aResFace = BRepBuilderAPI_MakeFace(result, Precision::Confusion());
384
385     bIsInfinit = Standard_True;
386   }
387   else
388     bIsInfinit = Standard_False;
389 }
390
391 //------------------------------------------------------------------------------
392 // static function: PERFORM_C0
393 //------------------------------------------------------------------------------
394 static void PERFORM_C0(const TopoDS_Edge &S1, const TopoDS_Edge &S2,
395                        BRepExtrema_SeqOfSolution& SeqSol1,
396                        BRepExtrema_SeqOfSolution& SeqSol2,
397                        const Standard_Real DstRef,
398                        Standard_Real& mDstRef,
399                        const Standard_Real Eps)
400 {
401   if ( BRep_Tool::Degenerated(S1) || BRep_Tool::Degenerated(S2) )
402     return;
403
404   Standard_Integer iE;
405   for (iE = 0; iE < 2; iE++)
406   {
407     TopoDS_Edge E, Eother;
408     if (iE == 0)
409         {
410           E      = S1;
411           Eother = S2;
412         }
413     else
414         {
415           E      = S2;
416           Eother = S1;
417         }
418
419     Standard_Real aFirst, aLast;
420     Handle(Geom_Curve) pCurv = BRep_Tool::Curve(E, aFirst, aLast);
421
422     Standard_Real aFOther, aLOther;
423     Handle(Geom_Curve) pCurvOther = BRep_Tool::Curve(Eother, aFOther, aLOther);
424
425     if (pCurv->Continuity() == GeomAbs_C0)
426         {
427       const Standard_Real epsP = Precision::PConfusion();
428
429       GeomAdaptor_Curve aAdaptorCurve(pCurv, aFirst, aLast);
430       const Standard_Integer nbIntervals = aAdaptorCurve.NbIntervals(GeomAbs_C1);
431
432       TColStd_Array1OfReal arrInter(1,1+nbIntervals);
433       aAdaptorCurve.Intervals(arrInter, GeomAbs_C1);
434
435       GeomAdaptor_Curve aAdaptorCurveOther(pCurvOther, aFOther, aLOther);
436       const Standard_Integer nbIntervalsOther = aAdaptorCurveOther.NbIntervals(GeomAbs_C1);
437       TColStd_Array1OfReal arrInterOther(1,1+nbIntervalsOther);
438       aAdaptorCurveOther.Intervals(arrInterOther, GeomAbs_C1);
439
440       Standard_Real Udeb,Ufin;
441       BRep_Tool::Range(Eother,Udeb,Ufin);
442
443       gp_Pnt P1,Pt;
444       Standard_Integer i, ii;  
445       BRepClass_FaceClassifier classifier;
446       for (i = 1; i <= arrInter.Length(); i++)
447       {
448         const Standard_Real aParameter = arrInter(i);
449         const gp_Pnt aPnt = aAdaptorCurve.Value(aParameter);
450         const TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(aPnt);
451
452         BRepExtrema_ExtPC Ext(V1,Eother);
453         const Standard_Integer NbExtrema = Ext.IsDone()? Ext.NbExt() : 0;
454         if ( NbExtrema > 0 )
455                 { 
456           // Search minimum distance dstmin
457           Standard_Real Dstmin = Ext.SquareDistance(1);
458           for (ii = 2; ii <= NbExtrema; ii++)
459           {
460             const Standard_Real sDst = Ext.SquareDistance(ii);
461             if (sDst<Dstmin)
462               Dstmin=sDst;
463           }
464           Dstmin = sqrt(Dstmin);
465
466           if ((Dstmin < DstRef - Eps) || (fabs(Dstmin-DstRef) < Eps))
467             for (ii = 1; ii <= NbExtrema; ii++)
468             {
469               if (fabs(Dstmin-sqrt(Ext.SquareDistance(ii)))<Eps)
470               {
471                 Pt=Ext.Point(ii);
472                 if (TRI_SOLUTION(SeqSol2,Pt))
473                 {
474                   // Check if the parameter does not correspond to a vertex
475                   const Standard_Real t = Ext.Parameter(ii);
476                   if ((fabs(t-Udeb)>=epsP)&&(fabs(t-Ufin)>epsP))
477                   {
478                     if (mDstRef > Dstmin)
479                       mDstRef=Dstmin;
480                     const BRepExtrema_SolutionElem Sol1(Dstmin,aPnt,BRepExtrema_IsOnEdge,E,aParameter);
481                     const BRepExtrema_SolutionElem Sol2(Dstmin,Pt,BRepExtrema_IsOnEdge,Eother,t);
482                     SeqSol1.Append(iE == 0 ? Sol1 : Sol2);
483                     SeqSol2.Append(iE == 0 ? Sol2 : Sol1);
484                   }
485                 }
486               }
487             }
488         }
489         for (Standard_Integer i2 = 1; i2<=arrInterOther.Length(); i2++)
490         {
491           const Standard_Real aParameterOther = arrInterOther(i2);
492           const gp_Pnt aPntOther = aAdaptorCurveOther.Value(aParameterOther);
493           const Standard_Real Dst = aPnt.Distance(aPntOther);
494           if ((Dst < DstRef - Eps) || (fabs(Dst-DstRef) < Eps))
495           {             
496             if (mDstRef > Dst)
497               mDstRef=Dst;
498             const BRepExtrema_SolutionElem Sol1(Dst,aPnt,BRepExtrema_IsOnEdge,E,aParameter);
499             const BRepExtrema_SolutionElem Sol2(Dst,aPntOther,BRepExtrema_IsOnEdge,Eother,aParameterOther);
500             SeqSol1.Append(iE == 0 ? Sol1 : Sol2);
501             SeqSol2.Append(iE == 0 ? Sol2 : Sol1);
502           }               
503         }
504       }
505     }
506   }
507 }
508
509 /*********************************************************************************/
510
511 void BRepExtrema_DistanceSS::Perform(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
512                                      const Bnd_Box& B1, const Bnd_Box& B2)
513 {
514   SeqSolShape1.Clear();
515   SeqSolShape2.Clear();
516   myModif=Standard_False;
517
518   switch (S1.ShapeType())
519   {
520     case TopAbs_VERTEX :
521     {
522       TopoDS_Vertex V1 = TopoDS::Vertex(S1);
523       switch (S2.ShapeType())
524       {
525         case TopAbs_VERTEX :
526         {
527           TopoDS_Vertex V2 = TopoDS::Vertex(S2);
528           Perform( V1, V2 );
529           break;
530         }
531         case TopAbs_EDGE :
532         {
533           TopoDS_Edge E2 = TopoDS::Edge(S2);
534           Perform( V1, E2, B1, B2 );
535           break;
536         }
537         case TopAbs_FACE :
538         {
539           TopoDS_Face F2 = TopoDS::Face(S2);
540           Perform( V1, F2, B1, B2 );
541           break;
542         }
543         default:
544           break;
545       }
546       break;
547     }
548
549     case TopAbs_EDGE :
550     {
551       TopoDS_Edge E1 = TopoDS::Edge(S1);
552       switch (S2.ShapeType())
553       {
554         case TopAbs_VERTEX :
555         {
556           TopoDS_Vertex V2 = TopoDS::Vertex(S2);
557           Perform( E1, V2, B1, B2 );
558           break;
559         }
560         case TopAbs_EDGE :
561         {
562           TopoDS_Edge E2 = TopoDS::Edge(S2);
563           TopoDS_Edge aTrimEdge;
564           Standard_Boolean bIsTrim1 = Standard_False;
565           Standard_Boolean bIsTrim2 = Standard_False;
566           TRIM_INFINIT_EDGE( E1, E2, aTrimEdge, bIsTrim1, bIsTrim2 );
567           if (bIsTrim1)
568             E1 = aTrimEdge;
569           if (bIsTrim2)
570             E2 = aTrimEdge;
571           Perform( E1, E2, B1, B2 );
572           break;
573         }
574         case TopAbs_FACE :
575         {
576           TopoDS_Face F2 = TopoDS::Face(S2);
577           TopoDS_Face aTrimFace;
578           Standard_Boolean bIsInfinit;
579           TRIM_INFINIT_FACE( E1, F2, aTrimFace, bIsInfinit );
580           if (bIsInfinit)
581             F2 = aTrimFace;
582           Perform( E1, F2, B1, B2 );
583           break;
584         }
585         default:
586           break;
587       }
588       break;
589     }
590
591     case TopAbs_FACE :
592     {
593       TopoDS_Face F1 = TopoDS::Face(S1);
594       switch (S2.ShapeType())
595       {
596         case TopAbs_VERTEX :
597         {
598           TopoDS_Vertex V2 = TopoDS::Vertex(S2);
599           Perform( F1, V2, B1, B2 );
600           break;
601         }
602         case TopAbs_EDGE :
603         {
604           TopoDS_Edge E2 = TopoDS::Edge(S2);
605           TopoDS_Face aTrimFace;
606           Standard_Boolean bIsInfinit;
607           TRIM_INFINIT_FACE( F1, E2, aTrimFace, bIsInfinit );
608           if (bIsInfinit)
609             F1 = aTrimFace;
610           Perform( F1, E2, B1, B2 );
611           break;
612         }
613         case TopAbs_FACE :
614         {
615           TopoDS_Face F2 = TopoDS::Face(S2);
616           Perform( F1, F2, B1, B2 );
617           break;
618         }
619         default:
620           break;
621       }
622       break;
623     }
624     default:
625       break;
626   }
627 }
628
629 /*********************************************************************************/
630
631 void BRepExtrema_DistanceSS::Perform(const TopoDS_Vertex& S1, const TopoDS_Vertex& S2)
632 {     
633   const gp_Pnt P1 = BRep_Tool::Pnt(S1);
634   const gp_Pnt P2 = BRep_Tool::Pnt(S2);
635
636   const Standard_Real Dst = P1.Distance(P2);
637   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
638   { 
639     if (myDstRef > Dst)
640       myDstRef=Dst;
641     myModif=Standard_True;
642     const BRepExtrema_SolutionElem Sol1(Dst,P1,BRepExtrema_IsVertex,S1);
643     const BRepExtrema_SolutionElem Sol2(Dst,P2,BRepExtrema_IsVertex,S2);
644     SeqSolShape1.Append(Sol1);
645     SeqSolShape2.Append(Sol2);
646   }
647 }
648
649 /*********************************************************************************/
650
651 void BRepExtrema_DistanceSS::Perform(const TopoDS_Vertex& S1, const TopoDS_Edge& S2,
652                                      const Bnd_Box& B1, const Bnd_Box& B2)
653
654   if (BRep_Tool::Degenerated(S2))
655     return;
656
657   const Standard_Real Dst=B1.Distance(B2);
658   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
659   {
660     BRepExtrema_ExtPC Ext(S1,S2);
661     const Standard_Integer NbExtrema = Ext.IsDone()? Ext.NbExt() : 0;
662     if ( NbExtrema > 0 )
663     {
664       // Search minimum distance Dstmin
665       Standard_Integer i;
666       Standard_Real Dstmin = Ext.SquareDistance(1);
667       for (i = 2; i <= NbExtrema; i++)
668       {
669         const Standard_Real sDst = Ext.SquareDistance(i);
670         if (sDst<Dstmin)
671           Dstmin=sDst;
672           }
673       Dstmin = sqrt(Dstmin);
674       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
675       {
676         Standard_Real Udeb,Ufin;
677         BRep_Tool::Range(S2,Udeb,Ufin);
678
679         gp_Pnt Pt,P1=BRep_Tool::Pnt(S1);
680         const Standard_Real epsP=Precision::PConfusion();
681
682         for (i = 1; i <= NbExtrema; i++)
683         {
684           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
685           {
686             Pt=Ext.Point(i);
687             if (TRI_SOLUTION(SeqSolShape2,Pt))
688             {
689               // Check if the parameter does not correspond to a vertex
690               const Standard_Real t = Ext.Parameter(i);
691               if ( (fabs(t-Udeb)>=epsP) && (fabs(t-Ufin)>epsP) )
692               {
693                 if (myDstRef > Dstmin)
694                   myDstRef=Dstmin;
695                 myModif=Standard_True;
696                 const BRepExtrema_SolutionElem Sol1(Dstmin,P1,BRepExtrema_IsVertex,S1);
697                 const BRepExtrema_SolutionElem Sol2(Dstmin,Pt,BRepExtrema_IsOnEdge,S2,t);
698                 SeqSolShape1.Append(Sol1);
699                 SeqSolShape2.Append(Sol2);
700               }
701             }
702           }
703         }
704       }
705     }
706   }
707 }
708
709 void BRepExtrema_DistanceSS::Perform(const TopoDS_Edge& S1,const TopoDS_Vertex& S2,
710                                      const Bnd_Box& B1,const Bnd_Box& B2)
711 {
712   if (BRep_Tool::Degenerated(S1))
713     return;
714
715   const Standard_Real Dst=B1.Distance(B2);
716   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
717   {
718     BRepExtrema_ExtPC Ext(S2,S1);
719     const Standard_Integer NbExtrema = Ext.IsDone()? Ext.NbExt() : 0;
720     if ( NbExtrema > 0 )
721     {
722       // Search minimum distance Dstmin
723       Standard_Integer i;
724       Standard_Real Dstmin = Ext.SquareDistance(1);
725       for (i = 2; i <= NbExtrema; i++)
726       {
727         const Standard_Real sDst = Ext.SquareDistance(i);
728         if (sDst<Dstmin)
729           Dstmin=sDst;
730           }
731       Dstmin = sqrt(Dstmin);
732       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
733       {
734         Standard_Real Udeb,Ufin;
735         BRep_Tool::Range(S1,Udeb,Ufin);
736
737         gp_Pnt Pt, P2 = BRep_Tool::Pnt(S2);
738         const Standard_Real epsP=Precision::PConfusion();
739
740         for (i = 1; i <= NbExtrema; i++)
741         {
742           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
743           {
744             Pt=Ext.Point(i);
745             if (TRI_SOLUTION(SeqSolShape1,Pt))
746             {
747               // Check if the parameter does not correspond to a vertex
748               const Standard_Real t = Ext.Parameter(i);
749               if ( (fabs(t-Udeb)>=epsP) && (fabs(t-Ufin)>epsP) )
750               {
751                 if (myDstRef > Dstmin)
752                   myDstRef=Dstmin;
753                 myModif=Standard_True;
754                 const BRepExtrema_SolutionElem Sol1(Dstmin,Pt,BRepExtrema_IsOnEdge,S1,t);
755                 const BRepExtrema_SolutionElem Sol2(Dstmin,P2,BRepExtrema_IsVertex,S2);
756                 SeqSolShape1.Append(Sol1);
757                 SeqSolShape2.Append(Sol2);
758               }
759             }
760           }
761         }
762       }
763     }
764   }
765 }
766
767 /*********************************************************************************/
768
769 void BRepExtrema_DistanceSS::Perform(const TopoDS_Vertex& S1, const TopoDS_Face& S2, 
770                                      const Bnd_Box& B1, const Bnd_Box& B2)
771 {
772   const Standard_Real Dst=B1.Distance(B2);
773   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
774   { 
775     BRepExtrema_ExtPF Ext(S1,S2,myFlag,myAlgo);
776     const Standard_Integer NbExtrema = Ext.IsDone()? Ext.NbExt() : 0;
777     if ( NbExtrema > 0 )
778     {
779       // Search minimum distance Dstmin
780       Standard_Integer i;
781       Standard_Real Dstmin = Ext.SquareDistance(1);
782       for (i = 2; i <= NbExtrema; i++)
783       {
784         const Standard_Real sDst = Ext.SquareDistance(i);
785         if (sDst<Dstmin) 
786           Dstmin=sDst;
787       }
788       Dstmin = sqrt(Dstmin);
789       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
790       {
791         Standard_Real U,V;
792         gp_Pnt Pt,P1=BRep_Tool::Pnt(S1);
793         BRepClass_FaceClassifier classifier;
794         const Standard_Real tol = BRep_Tool::Tolerance(S2);
795  
796         for (i = 1; i <= NbExtrema; i++)
797         {
798           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
799           {
800             Pt=Ext.Point(i);
801             if (TRI_SOLUTION(SeqSolShape2,Pt))
802             {
803               // Check if the parameter does not correspond to a vertex
804               Ext.Parameter(i,U,V);
805               const gp_Pnt2d PUV(U,V);
806               classifier.Perform(S2,PUV,tol);
807               if (classifier.State()==TopAbs_IN)
808               {
809                 if (myDstRef > Dstmin)
810                   myDstRef=Dstmin;
811                 myModif=Standard_True;
812                 const BRepExtrema_SolutionElem Sol1(Dstmin,P1,BRepExtrema_IsVertex,S1);
813                 const BRepExtrema_SolutionElem Sol2(Dstmin,Pt,BRepExtrema_IsInFace,S2,U,V);
814                 SeqSolShape1.Append(Sol1);
815                 SeqSolShape2.Append(Sol2);                
816               }
817             }
818           }
819         }
820       }
821     }
822   }
823 }
824
825 void BRepExtrema_DistanceSS::Perform(const TopoDS_Face& S1, const TopoDS_Vertex& S2, 
826                                      const Bnd_Box& B1, const Bnd_Box& B2)
827 {
828   const Standard_Real Dst=B1.Distance(B2);
829   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
830   { 
831     BRepExtrema_ExtPF Ext(S2,S1,myFlag,myAlgo);
832     const Standard_Integer NbExtrema = Ext.IsDone()? Ext.NbExt() : 0;
833     if ( NbExtrema > 0 )
834     {
835       // Search minimum distance Dstmin
836       Standard_Integer i;
837       Standard_Real Dstmin = Ext.SquareDistance(1);
838       for (i = 2; i <= NbExtrema; i++)
839       {
840         const Standard_Real sDst = Ext.SquareDistance(i);
841         if (sDst<Dstmin) 
842           Dstmin=sDst;
843       }
844       Dstmin = sqrt(Dstmin);
845       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
846       {
847         Standard_Real U,V;
848         gp_Pnt Pt,P2=BRep_Tool::Pnt(S2);
849         BRepClass_FaceClassifier classifier;
850         const Standard_Real tol = BRep_Tool::Tolerance(S1);
851  
852         for (i = 1; i <= NbExtrema; i++)
853         {
854           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
855           {
856             Pt=Ext.Point(i);
857             if (TRI_SOLUTION(SeqSolShape1,Pt))
858             {
859               // Check if the parameter does not correspond to a vertex
860               Ext.Parameter(i,U,V);
861               const gp_Pnt2d PUV(U,V);
862               classifier.Perform(S1,PUV,tol);
863               if (classifier.State()==TopAbs_IN)
864               {
865                 if (myDstRef > Dstmin)
866                   myDstRef=Dstmin;
867                 myModif=Standard_True;
868                 const BRepExtrema_SolutionElem Sol1(Dstmin,Pt,BRepExtrema_IsInFace,S1,U,V);
869                 const BRepExtrema_SolutionElem Sol2(Dstmin,P2,BRepExtrema_IsVertex,S2);
870                 SeqSolShape1.Append(Sol1);
871                 SeqSolShape2.Append(Sol2);                
872               }
873             }
874           }
875         }
876       }
877     }
878   }
879 }
880
881 /*********************************************************************************/
882
883 void BRepExtrema_DistanceSS::Perform(const TopoDS_Edge& S1, const TopoDS_Edge& S2,
884                                      const Bnd_Box& B1, const Bnd_Box& B2)
885 {
886   if (BRep_Tool::Degenerated(S1) || BRep_Tool::Degenerated(S2))
887     return;
888
889   const Standard_Real Dst=B1.Distance(B2);
890   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
891   {
892     const Standard_Real DstRef = myDstRef;
893
894     BRepExtrema_ExtCC Ext(S1,S2);
895         const Standard_Integer NbExtrema = Ext.IsDone()? (Ext.IsParallel()? 0 : Ext.NbExt()) : 0;
896     if ( NbExtrema > 0 )
897     {
898       // Search minimum distance Dstmin
899       Standard_Integer i;
900       Standard_Real Dstmin = Ext.SquareDistance(1);
901       for (i = 2; i <= NbExtrema; i++)
902       {
903         const Standard_Real sDst = Ext.SquareDistance(i);
904         if (sDst<Dstmin) 
905           Dstmin=sDst;
906           }
907       Dstmin = sqrt(Dstmin);
908       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
909       {
910         Standard_Real Udeb1,Ufin1,Udeb2,Ufin2;
911         BRep_Tool::Range(S1,Udeb1,Ufin1);
912         BRep_Tool::Range(S2,Udeb2,Ufin2);
913
914         gp_Pnt Pt1,Pt2;
915         const Standard_Real epsP=Precision::PConfusion();
916
917         for (i=1;i<=NbExtrema;i++)
918         {
919           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
920           {
921             Pt1=Ext.PointOnE1(i);
922             Pt2=Ext.PointOnE2(i);
923             if (TRI_SOLUTION(SeqSolShape1,Pt1) || TRI_SOLUTION(SeqSolShape2,Pt2))
924             {
925               // Check if the parameters do not correspond to a vertex
926               const Standard_Real t1 = Ext.ParameterOnE1(i);
927               const Standard_Real t2 = Ext.ParameterOnE2(i);
928               if ((fabs(t1-Udeb1)>=epsP)&&(fabs(t1-Ufin1)>epsP)&&(fabs(t2-Udeb2)>=epsP)&&(fabs(t2-Ufin2)>epsP))
929               {
930                 if (myDstRef > Dstmin)
931                   myDstRef=Dstmin;
932                 myModif=Standard_True;
933                 const BRepExtrema_SolutionElem Sol1(Dstmin,Pt1,BRepExtrema_IsOnEdge,S1,t1);
934                 const BRepExtrema_SolutionElem Sol2(Dstmin,Pt2,BRepExtrema_IsOnEdge,S2,t2);
935                 SeqSolShape1.Append(Sol1);
936                 SeqSolShape2.Append(Sol2);
937               }
938             }
939           }
940         }
941       }
942     }
943
944     BRepExtrema_SeqOfSolution SeqSolution1;
945     BRepExtrema_SeqOfSolution SeqSolution2;
946
947     PERFORM_C0(S1, S2, SeqSolution1, SeqSolution2, DstRef, myDstRef, myEps);
948      
949     BRepExtrema_SeqOfSolution seqSol1;
950     BRepExtrema_SeqOfSolution seqSol2;
951         
952     if (SeqSolution1.Length() > 0 && SeqSolution2.Length() > 0)
953       MIN_SOLUTION(SeqSolution1, SeqSolution2, myDstRef, myEps, seqSol1, seqSol2);
954      
955     if (!seqSol1.IsEmpty() && !seqSol2.IsEmpty())
956     {
957       SeqSolShape1.Append(seqSol1);
958       SeqSolShape2.Append(seqSol2);     
959       myModif = Standard_True;
960     }
961   }
962 }
963
964 /*********************************************************************************/
965
966 void BRepExtrema_DistanceSS::Perform(const TopoDS_Edge& S1, const TopoDS_Face& S2,
967                                      const Bnd_Box& B1, const Bnd_Box& B2)
968 {
969   if (BRep_Tool::Degenerated(S1))
970     return;
971     
972   const Standard_Real Dst=B1.Distance(B2);
973   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
974   {
975     BRepClass_FaceClassifier classifier;
976
977     BRepExtrema_ExtCF Ext(S1,S2);
978         const Standard_Integer NbExtrema = Ext.IsDone()? (Ext.IsParallel()? 0 : Ext.NbExt()) : 0;
979     if ( NbExtrema > 0 )
980     {
981       // Search minimum distance Dstmin
982       Standard_Integer i;
983       Standard_Real Dstmin = Ext.SquareDistance(1);
984       for (i = 2; i <= NbExtrema; i++)
985       {
986         const Standard_Real sDst = Ext.SquareDistance(i);
987         if (sDst<Dstmin) 
988           Dstmin=sDst;
989       }
990       Dstmin = sqrt(Dstmin);
991       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
992       {
993         Standard_Real Udeb,Ufin,U,V;
994         BRep_Tool::Range(S1,Udeb,Ufin);
995         const Standard_Real tol=BRep_Tool::Tolerance(S2);
996
997         gp_Pnt Pt1,Pt2;
998         const Standard_Real epsP=Precision::PConfusion();
999
1000         for (i = 1; i <= NbExtrema; i++)
1001         {
1002           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
1003           {
1004             Pt1=Ext.PointOnEdge(i);
1005             Pt2=Ext.PointOnFace(i);
1006             if (TRI_SOLUTION(SeqSolShape1,Pt1) || TRI_SOLUTION(SeqSolShape2,Pt2))
1007             {
1008               // Check if the parameter does not correspond to a vertex
1009               const Standard_Real t1 = Ext.ParameterOnEdge(i);
1010               if ((fabs(t1-Udeb)>=epsP)&&(fabs(t1-Ufin)>epsP))
1011               {
1012                 Ext.ParameterOnFace(i,U,V);
1013                 const gp_Pnt2d PUV(U,V);
1014                 classifier.Perform(S2,PUV,tol);
1015                 if (classifier.State()==TopAbs_IN)
1016                 {
1017                   if (myDstRef > Dstmin)
1018                     myDstRef=Dstmin;
1019                   myModif=Standard_True;
1020                   const BRepExtrema_SolutionElem Sol1(Dstmin,Pt1,BRepExtrema_IsOnEdge,S1,t1);
1021                   const BRepExtrema_SolutionElem Sol2(Dstmin,Pt2,BRepExtrema_IsInFace,S2,U,V);
1022                   SeqSolShape1.Append(Sol1);
1023                   SeqSolShape2.Append(Sol2);              
1024                 }
1025               }
1026             }
1027           }
1028         }
1029       }
1030     }
1031
1032     Standard_Real aFirst, aLast;
1033     Handle(Geom_Curve) pCurv = BRep_Tool::Curve(S1, aFirst, aLast);
1034     if (pCurv->Continuity() == GeomAbs_C0)
1035     {
1036       BRepExtrema_SeqOfSolution SeqSolution1;
1037       BRepExtrema_SeqOfSolution SeqSolution2;
1038
1039       GeomAdaptor_Curve aAdaptorCurve(pCurv, aFirst, aLast);
1040       const Standard_Integer nbIntervals = aAdaptorCurve.NbIntervals(GeomAbs_C1);
1041
1042       TColStd_Array1OfReal arrInter(1,1+nbIntervals);
1043       aAdaptorCurve.Intervals(arrInter, GeomAbs_C1);
1044
1045       gp_Pnt Pt;
1046       Standard_Real U,V;
1047       const Standard_Real tol = BRep_Tool::Tolerance(S2);
1048
1049       Standard_Integer i;
1050       for (i = 1; i <= arrInter.Length(); i++)
1051       {
1052         const Standard_Real aParameter = arrInter(i);
1053         gp_Pnt aPnt = aAdaptorCurve.Value(aParameter);
1054         TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(aPnt);
1055
1056         BRepExtrema_ExtPF ExtPF(V1,S2);
1057         const Standard_Integer NbExtremaPF = ExtPF.IsDone()? ExtPF.NbExt() : 0;
1058         if (NbExtremaPF > 0 )
1059         {
1060           // Search minimum distance Dstmin
1061           Standard_Integer ii;
1062           Standard_Real Dstmin = ExtPF.SquareDistance(1);
1063           for (ii = 2; ii <= NbExtremaPF; ii++)
1064           {
1065             const Standard_Real sDst = ExtPF.SquareDistance(ii);
1066             if (sDst<Dstmin)
1067               Dstmin=sDst;
1068           }
1069           Dstmin = sqrt(Dstmin);
1070
1071           if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
1072           {
1073             for (ii = 1; ii <= NbExtremaPF; ii++)
1074             { 
1075               if (fabs(Dstmin-sqrt(ExtPF.SquareDistance(ii)))<myEps)
1076               { 
1077                 // Check if the parameter does not correspond to a vertex
1078                 ExtPF.Parameter(ii,U,V);
1079                 const gp_Pnt2d PUV(U,V);
1080                                 classifier.Perform(S2,PUV,tol);
1081                 if (classifier.State()==TopAbs_IN)
1082                 {
1083                   if (myDstRef > Dstmin)
1084                     myDstRef=Dstmin;
1085                   myModif=Standard_True;
1086                   const BRepExtrema_SolutionElem Sol1(Dstmin,aPnt,BRepExtrema_IsOnEdge,S1,aParameter);
1087                   const BRepExtrema_SolutionElem Sol2(Dstmin,ExtPF.Point(ii),BRepExtrema_IsInFace,S2,U,V);
1088                   SeqSolution1.Append(Sol1);
1089                   SeqSolution2.Append(Sol2);
1090                 }
1091               }
1092             }
1093           }
1094         }
1095       }
1096
1097       BRepExtrema_SeqOfSolution seqSol1;
1098       BRepExtrema_SeqOfSolution seqSol2;
1099       if (SeqSolution1.Length() > 0 && SeqSolution2.Length() > 0)
1100         MIN_SOLUTION(SeqSolution1, SeqSolution2, myDstRef, myEps, seqSol1, seqSol2);
1101             
1102       if (!seqSol1.IsEmpty() && !seqSol2.IsEmpty())
1103       {
1104         SeqSolShape1.Append(seqSol1);
1105         SeqSolShape2.Append(seqSol2);
1106       }
1107     }
1108   }
1109 }
1110
1111 void BRepExtrema_DistanceSS::Perform(const TopoDS_Face& S1, const TopoDS_Edge& S2,
1112                                      const Bnd_Box& B1, const Bnd_Box& B2)
1113 {
1114   if (BRep_Tool::Degenerated(S2))
1115     return;
1116     
1117   const Standard_Real Dst=B1.Distance(B2);
1118   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
1119   {
1120     BRepClass_FaceClassifier classifier;
1121
1122     BRepExtrema_ExtCF Ext(S2,S1);
1123         const Standard_Integer NbExtrema = Ext.IsDone()? (Ext.IsParallel()? 0 : Ext.NbExt()) : 0;
1124     if ( NbExtrema > 0 )
1125     {
1126       // Search minimum distance Dstmin
1127       Standard_Integer i;
1128       Standard_Real Dstmin = Ext.SquareDistance(1);
1129       for (i = 2; i <= NbExtrema; i++)
1130       {
1131         const Standard_Real sDst = Ext.SquareDistance(i);
1132         if (sDst<Dstmin) 
1133           Dstmin=sDst;
1134       }
1135       Dstmin = sqrt(Dstmin);
1136       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
1137       {
1138         Standard_Real Udeb,Ufin,U,V;
1139         BRep_Tool::Range(S2,Udeb,Ufin);
1140         const Standard_Real tol=BRep_Tool::Tolerance(S1);
1141
1142         gp_Pnt Pt1,Pt2;
1143         const Standard_Real epsP=Precision::PConfusion();
1144
1145         for (i = 1; i <= NbExtrema; i++)
1146         {
1147           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
1148           {
1149             Pt1=Ext.PointOnEdge(i);
1150             Pt2=Ext.PointOnFace(i);
1151             if (TRI_SOLUTION(SeqSolShape1,Pt1) || TRI_SOLUTION(SeqSolShape2,Pt2))
1152             {
1153               // Check if the parameter does not correspond to a vertex
1154               const Standard_Real t1 = Ext.ParameterOnEdge(i);
1155               if ((fabs(t1-Udeb)>=epsP)&&(fabs(t1-Ufin)>epsP))
1156               {
1157                 Ext.ParameterOnFace(i,U,V);
1158                 const gp_Pnt2d PUV(U,V);
1159                 classifier.Perform(S1,PUV,tol);
1160                 if (classifier.State()==TopAbs_IN)
1161                 {
1162                   if (myDstRef > Dstmin)
1163                     myDstRef=Dstmin;
1164                   myModif=Standard_True;
1165                   const BRepExtrema_SolutionElem Sol2(Dstmin,Pt1,BRepExtrema_IsOnEdge,S2,t1);
1166                   const BRepExtrema_SolutionElem Sol1(Dstmin,Pt2,BRepExtrema_IsInFace,S1,U,V);
1167                   SeqSolShape1.Append(Sol1);
1168                   SeqSolShape2.Append(Sol2);              
1169                 }
1170               }
1171             }
1172           }
1173         }
1174       }
1175     }
1176
1177     Standard_Real aFirst, aLast;
1178     Handle(Geom_Curve) pCurv = BRep_Tool::Curve(S2, aFirst, aLast);
1179     if (pCurv->Continuity() == GeomAbs_C0)
1180     {
1181       BRepExtrema_SeqOfSolution SeqSolution1;
1182       BRepExtrema_SeqOfSolution SeqSolution2;
1183
1184       GeomAdaptor_Curve aAdaptorCurve(pCurv, aFirst, aLast);
1185       const Standard_Integer nbIntervals = aAdaptorCurve.NbIntervals(GeomAbs_C1);
1186
1187       TColStd_Array1OfReal arrInter(1,1+nbIntervals);
1188       aAdaptorCurve.Intervals(arrInter, GeomAbs_C1);
1189
1190       gp_Pnt Pt;
1191       Standard_Real U,V;
1192       const Standard_Real tol = BRep_Tool::Tolerance(S1);
1193
1194       Standard_Integer i;
1195       for (i = 1; i <= arrInter.Length(); i++)
1196       {
1197         const Standard_Real aParameter = arrInter(i);
1198         gp_Pnt aPnt = aAdaptorCurve.Value(aParameter);
1199         TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(aPnt);
1200
1201         BRepExtrema_ExtPF ExtPF(V1,S1);
1202         const Standard_Integer NbExtremaPF = ExtPF.IsDone()? ExtPF.NbExt() : 0;
1203         if (NbExtremaPF > 0 )
1204         {
1205           // Search minimum distance Dstmin
1206           Standard_Integer ii;
1207           Standard_Real Dstmin = ExtPF.SquareDistance(1);
1208           for (ii = 2; ii <= NbExtremaPF; ii++)
1209           {
1210             const Standard_Real sDst = ExtPF.SquareDistance(ii);
1211             if (sDst<Dstmin)
1212               Dstmin=sDst;
1213           }
1214           Dstmin = sqrt(Dstmin);
1215
1216           if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
1217           {
1218             for (ii = 1; ii <= NbExtremaPF; ii++)
1219             { 
1220               if (fabs(Dstmin-sqrt(ExtPF.SquareDistance(ii)))<myEps)
1221               { 
1222                 // Check if the parameter does not correspond to a vertex
1223                 ExtPF.Parameter(ii,U,V);
1224                 const gp_Pnt2d PUV(U,V);
1225                                 classifier.Perform(S1,PUV,tol);
1226                 if (classifier.State()==TopAbs_IN)
1227                 {
1228                   if (myDstRef > Dstmin)
1229                     myDstRef=Dstmin;
1230                   myModif=Standard_True;
1231                   const BRepExtrema_SolutionElem Sol2(Dstmin,aPnt,BRepExtrema_IsOnEdge,S2,aParameter);
1232                   const BRepExtrema_SolutionElem Sol1(Dstmin,ExtPF.Point(ii),BRepExtrema_IsInFace,S1,U,V);
1233                   SeqSolution1.Append(Sol1);
1234                   SeqSolution2.Append(Sol2);
1235                 }
1236               }
1237             }
1238           }
1239         }
1240       }
1241
1242       BRepExtrema_SeqOfSolution seqSol1;
1243       BRepExtrema_SeqOfSolution seqSol2;
1244       if (SeqSolution1.Length() > 0 && SeqSolution2.Length() > 0)
1245         MIN_SOLUTION(SeqSolution1, SeqSolution2, myDstRef, myEps, seqSol1, seqSol2);
1246             
1247       if (!seqSol1.IsEmpty() && !seqSol2.IsEmpty())
1248       {
1249         SeqSolShape1.Append(seqSol1);
1250         SeqSolShape2.Append(seqSol2);
1251       }
1252     }
1253   }
1254 }
1255
1256 /*********************************************************************************/
1257
1258 void BRepExtrema_DistanceSS::Perform(const TopoDS_Face& S1, const TopoDS_Face& S2,
1259                                      const Bnd_Box& B1, const Bnd_Box& B2)
1260 {
1261   const Standard_Real Dst=B1.Distance(B2);
1262   if ((Dst < myDstRef - myEps) || (fabs(Dst-myDstRef) < myEps))
1263   { 
1264     BRepExtrema_ExtFF Ext(S1,S2);
1265         const Standard_Integer NbExtrema = Ext.IsDone()? (Ext.IsParallel()? 0 : Ext.NbExt()) : 0;
1266     if ( NbExtrema > 0 )
1267     {
1268       // Search minimum distance Dstmin
1269       Standard_Integer i;
1270       Standard_Real Dstmin = Ext.SquareDistance(1);
1271       for (i = 2; i <= NbExtrema; i++)
1272       {
1273         const Standard_Real sDst = Ext.SquareDistance(i);
1274         if (sDst<Dstmin)
1275           Dstmin=sDst;
1276       }
1277       Dstmin = sqrt(Dstmin);
1278       if ((Dstmin < myDstRef - myEps) || (fabs(Dstmin-myDstRef) < myEps))
1279       {
1280         const Standard_Real tol1=BRep_Tool::Tolerance(S1);
1281         const Standard_Real tol2=BRep_Tool::Tolerance(S2);
1282
1283         gp_Pnt Pt1,Pt2;
1284         gp_Pnt2d PUV;
1285         Standard_Real U1,V1,U2,V2;
1286         BRepClass_FaceClassifier classifier;
1287  
1288         for (i = 1; i <= NbExtrema; i++)
1289         {
1290           if (fabs(Dstmin-sqrt(Ext.SquareDistance(i)))<myEps)
1291           {
1292             Pt1=Ext.PointOnFace1(i);
1293             Pt2=Ext.PointOnFace2(i); 
1294             if (TRI_SOLUTION(SeqSolShape1,Pt1) || TRI_SOLUTION(SeqSolShape2,Pt2))
1295             {
1296               // Check if the parameter does not correspond to a vertex
1297               Ext.ParameterOnFace1(i,U1,V1);
1298               PUV.SetCoord(U1,V1);
1299               classifier.Perform(S1,PUV,tol1);
1300               if (classifier.State()==TopAbs_IN)
1301               {
1302                 Ext.ParameterOnFace2(i,U2,V2);
1303                 PUV.SetCoord(U2,V2);
1304                 classifier.Perform(S2,PUV,tol2);
1305                 if (classifier.State()==TopAbs_IN)
1306                 {
1307                   if (myDstRef > Dstmin)
1308                     myDstRef=Dstmin;
1309                   myModif=Standard_True;
1310                   const BRepExtrema_SolutionElem Sol1(Dstmin,Pt1,BRepExtrema_IsInFace,S1,U1,V1);
1311                   const BRepExtrema_SolutionElem Sol2(Dstmin,Pt2,BRepExtrema_IsInFace,S2,U2,V2);
1312                   SeqSolShape1.Append(Sol1);
1313                   SeqSolShape2.Append(Sol2);
1314                 }
1315               }
1316             }
1317           }
1318         }
1319       }
1320     }
1321   }
1322 }
1323
1324 /*********************************************************************************/