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