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