0031942: Modeling Algorithms - add possibility to abort the BRepExtrema_DistShapeShap...
[occt.git] / src / BRepExtrema / BRepExtrema_DistShapeShape.cxx
1 // Created on: 1996-04-22
2 // Created by: Herve LOUESSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified: Mps(10-04-97) portage WNT
18
19 #include <BRepExtrema_DistShapeShape.hxx>
20
21 #include <Standard_OStream.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Bnd_Box.hxx>
25 #include <TopExp.hxx>
26 #include <BRepExtrema_DistanceSS.hxx>
27 #include <TopoDS.hxx>
28 #include <TopAbs.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopAbs_ShapeEnum.hxx>
33 #include <Precision.hxx>
34 #include <Bnd_SeqOfBox.hxx>
35 #include <BRepExtrema_UnCompatibleShape.hxx>
36 #include <BRep_Tool.hxx>
37 #include <BRepClass3d_SolidClassifier.hxx>
38 #include <NCollection_Vector.hxx>
39 #include <StdFail_NotDone.hxx>
40
41 #include <algorithm>
42 namespace
43 {
44
45   static void Decomposition(const TopoDS_Shape&         S,
46                             TopTools_IndexedMapOfShape& MapV,
47                             TopTools_IndexedMapOfShape& MapE,
48                             TopTools_IndexedMapOfShape& MapF)
49   {
50     MapV.Clear();
51     MapE.Clear();
52     MapF.Clear();
53     TopExp::MapShapes(S,TopAbs_VERTEX,MapV);
54     TopExp::MapShapes(S,TopAbs_EDGE,MapE);
55     TopExp::MapShapes(S,TopAbs_FACE,MapF);
56   }
57
58   static void BoxCalculation(const TopTools_IndexedMapOfShape& Map,
59                              Bnd_SeqOfBox&                     SBox)
60   {
61     for (Standard_Integer i = 1; i <= Map.Extent(); i++)
62     {
63       Bnd_Box box;
64       BRepBndLib::Add(Map(i), box);
65       SBox.Append(box);
66     }
67   }
68
69   inline Standard_Real DistanceInitiale(const TopoDS_Vertex V1,
70                                         const TopoDS_Vertex V2)
71   {
72     return (BRep_Tool::Pnt(V1).Distance(BRep_Tool::Pnt(V2)));
73   }
74
75   //! Pair of objects to check extrema.
76   struct BRepExtrema_CheckPair
77   {
78     Standard_Integer Index1;   //!< Index of the 1st sub-shape
79     Standard_Integer Index2;   //!< Index of the 2nd sub-shape
80     Standard_Real    Distance; //!< Distance between sub-shapes
81
82     //! Uninitialized constructor for collection.
83     BRepExtrema_CheckPair()
84     : Index1(0),
85       Index2(0),
86       Distance(0.0)
87     {
88     }
89
90     //! Creates new pair of sub-shapes.
91     BRepExtrema_CheckPair (Standard_Integer theIndex1,
92                            Standard_Integer theIndex2,
93                            Standard_Real    theDistance)
94     : Index1   (theIndex1),
95       Index2   (theIndex2),
96       Distance (theDistance) {}
97   };
98
99   // Used by std::sort function
100   static Standard_Boolean BRepExtrema_CheckPair_Comparator (const BRepExtrema_CheckPair& theLeft,
101                                                             const BRepExtrema_CheckPair& theRight)
102   {
103     return (theLeft.Distance < theRight.Distance);
104   }
105 }
106
107 //=======================================================================
108 //function : DistanceMapMap
109 //purpose  : 
110 //=======================================================================
111
112 Standard_Boolean BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShape& theMap1,
113                                                              const TopTools_IndexedMapOfShape& theMap2,
114                                                              const Bnd_SeqOfBox&               theLBox1,
115                                                              const Bnd_SeqOfBox&               theLBox2,
116                                                              const Message_ProgressRange&      theRange)
117 {
118   NCollection_Vector<BRepExtrema_CheckPair> aPairList;
119   const Standard_Integer aCount1 = theMap1.Extent();
120   const Standard_Integer aCount2 = theMap2.Extent();
121
122   Message_ProgressScope aTwinScope(theRange, NULL, 1.0);
123   Message_ProgressRange aBoxRange(aTwinScope.Next(0.3));
124   Message_ProgressScope aBoxScope(aBoxRange, NULL, aCount1);
125
126   for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
127   {
128     aBoxScope.Next();
129     if (!aBoxScope.More())
130     {
131       return Standard_False;
132     }
133     for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
134     {
135       const Bnd_Box& aBox1 = theLBox1.Value (anIdx1);
136       const Bnd_Box& aBox2 = theLBox2.Value (anIdx2);
137       if (aBox1.IsVoid()
138        || aBox2.IsVoid())
139       {
140         continue;
141       }
142
143       const Standard_Real aDist = aBox1.Distance (aBox2);
144       if (aDist < myDistRef - myEps || fabs (aDist - myDistRef) < myEps)
145       {
146         aPairList.Append (BRepExtrema_CheckPair (anIdx1, anIdx2, aDist));
147       }
148     }
149   }
150
151   std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator);
152   Message_ProgressRange aDistRange(aTwinScope.Next(0.7));
153   Message_ProgressScope aDistScope(aDistRange, NULL, aPairList.Size());
154   for (NCollection_Vector<BRepExtrema_CheckPair>::Iterator aPairIter (aPairList);
155        aPairIter.More(); aPairIter.Next())
156   {
157     aDistScope.Next();
158     if (!aDistScope.More())
159     {
160       return Standard_False;
161     }
162     const BRepExtrema_CheckPair& aPair = aPairIter.Value();
163     if (aPair.Distance > myDistRef + myEps)
164     {
165       break; // early search termination
166     }
167
168     const Bnd_Box& aBox1 = theLBox1.Value (aPair.Index1);
169     const Bnd_Box& aBox2 = theLBox2.Value (aPair.Index2);
170
171     const TopoDS_Shape& aShape1 = theMap1 (aPair.Index1);
172     const TopoDS_Shape& aShape2 = theMap2 (aPair.Index2);
173
174     BRepExtrema_DistanceSS aDistTool (aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
175     if (aDistTool.IsDone())
176     {
177       if (aDistTool.DistValue() < myDistRef - myEps)
178       {
179         mySolutionsShape1.Clear();
180         mySolutionsShape2.Clear();
181
182         BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
183         BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
184
185         mySolutionsShape1.Append (aSeq1);
186         mySolutionsShape2.Append (aSeq2);
187
188         myDistRef = aDistTool.DistValue();
189       }
190       else if (fabs (aDistTool.DistValue() - myDistRef) < myEps)
191       {
192         BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
193         BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
194
195         mySolutionsShape1.Append (aSeq1);
196         mySolutionsShape2.Append (aSeq2);
197
198         if (myDistRef > aDistTool.DistValue())
199         {
200           myDistRef = aDistTool.DistValue();
201         }
202       }
203     }
204   }
205   return Standard_True;
206 }
207
208 //=======================================================================
209 //function : BRepExtrema_DistShapeShape
210 //purpose  : 
211 //=======================================================================
212
213 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
214 : myDistRef (0.0),
215   myIsDone (Standard_False),
216   myInnerSol (Standard_False),
217   myEps (Precision::Confusion()),
218   myIsInitS1 (Standard_False),
219   myIsInitS2 (Standard_False),
220   myFlag (Extrema_ExtFlag_MINMAX),
221   myAlgo (Extrema_ExtAlgo_Grad)
222 {
223   //
224 }
225
226 //=======================================================================
227 //function : BRepExtrema_DistShapeShape
228 //purpose  : 
229 //=======================================================================
230 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
231                                                        const TopoDS_Shape& Shape2,
232                                                        const Extrema_ExtFlag F,
233                                                        const Extrema_ExtAlgo A,
234                                                        const Message_ProgressRange& theRange)
235 : myDistRef (0.0),
236   myIsDone (Standard_False),
237   myInnerSol (Standard_False),
238   myEps (Precision::Confusion()),
239   myIsInitS1 (Standard_False),
240   myIsInitS2 (Standard_False),
241   myFlag (F),
242   myAlgo (A)
243 {
244   LoadS1(Shape1);
245   LoadS2(Shape2);
246   Perform(theRange);
247 }
248
249 //=======================================================================
250 //function : BRepExtrema_DistShapeShape
251 //purpose  : 
252 //=======================================================================
253
254 BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
255                                                        const TopoDS_Shape& Shape2,
256                                                        const Standard_Real theDeflection,
257                                                        const Extrema_ExtFlag F,
258                                                        const Extrema_ExtAlgo A,
259                                                        const Message_ProgressRange& theRange)
260 : myDistRef (0.0),
261   myIsDone (Standard_False),
262   myInnerSol (Standard_False),
263   myEps (theDeflection),
264   myIsInitS1 (Standard_False),
265   myIsInitS2 (Standard_False),
266   myFlag (F),
267   myAlgo (A)
268 {
269   LoadS1(Shape1);
270   LoadS2(Shape2);
271   Perform(theRange);
272 }
273
274 //=======================================================================
275 //function : LoadS1
276 //purpose  : 
277 //=======================================================================
278
279 void BRepExtrema_DistShapeShape::LoadS1 (const TopoDS_Shape& Shape1)
280 {
281   myShape1 = Shape1;
282   myIsInitS1 = Standard_False;
283   Decomposition (Shape1, myMapV1, myMapE1, myMapF1);
284 }
285
286 //=======================================================================
287 //function : LoadS2
288 //purpose  : 
289 //=======================================================================
290
291 void BRepExtrema_DistShapeShape::LoadS2 (const TopoDS_Shape& Shape2)
292 {
293   myShape2 = Shape2;
294   myIsInitS2 = Standard_False;
295   Decomposition (Shape2, myMapV2, myMapE2, myMapF2);
296 }
297
298 //=======================================================================
299 //function : SolidTreatment
300 //purpose  : 
301 //=======================================================================
302 Standard_Boolean BRepExtrema_DistShapeShape::SolidTreatment(const TopoDS_Shape& theShape,
303                                                             const TopTools_IndexedMapOfShape& theMap,
304                                                             const Message_ProgressRange& theRange)
305 {
306   BRepClass3d_SolidClassifier aClassifier(theShape);
307   const Standard_Real aTolerance = 0.001;
308   Message_ProgressScope aScope(theRange, NULL, theMap.Extent());
309   for (Standard_Integer i = 1; i < theMap.Extent(); ++i)
310   {
311     aScope.Next();
312     if (!aScope.More())
313     {
314       return Standard_False;
315     }
316     const TopoDS_Vertex& aVertex = TopoDS::Vertex(theMap(i));
317     const gp_Pnt& aPnt = BRep_Tool::Pnt(aVertex);
318     aClassifier.Perform(aPnt, aTolerance);
319     if (aClassifier.State() == TopAbs_IN)
320     {
321       myInnerSol = Standard_True;
322       myDistRef = 0.;
323       myIsDone = Standard_True;
324       BRepExtrema_SolutionElem Sol(0, aPnt, BRepExtrema_IsVertex, aVertex);
325       mySolutionsShape1.Append(Sol);
326       mySolutionsShape2.Append(Sol);
327       break;
328     }
329   }
330   return Standard_True;
331 }
332
333 //=======================================================================
334 //function : Perform
335 //purpose  : 
336 //=======================================================================
337
338 Standard_Boolean BRepExtrema_DistShapeShape::Perform(const Message_ProgressRange& theRange)
339 {
340   myIsDone=Standard_False;
341   myInnerSol=Standard_False;
342   mySolutionsShape1.Clear();
343   mySolutionsShape2.Clear();
344
345   if ( myShape1.IsNull() || myShape2.IsNull() )
346     return Standard_False;
347
348   // Treatment of solids
349   Standard_Boolean anIsSolid1 = (myShape1.ShapeType() == TopAbs_SOLID) ||
350                                 (myShape1.ShapeType() == TopAbs_COMPSOLID);
351   Standard_Boolean anIsSolid2 = (myShape2.ShapeType() == TopAbs_SOLID) ||
352                                 (myShape2.ShapeType() == TopAbs_COMPSOLID);
353   Standard_Integer aRootStepsNum = 9; // By num of DistanceMapMap calls
354   aRootStepsNum = anIsSolid1 ? aRootStepsNum+1 : aRootStepsNum;
355   aRootStepsNum = anIsSolid2 ? aRootStepsNum+1 : aRootStepsNum;
356   Message_ProgressScope aRootScope(theRange, "calculating distance", aRootStepsNum);
357
358   if (anIsSolid1)
359   {
360     if (!SolidTreatment(myShape1, myMapV2, aRootScope.Next()))
361     {
362       return Standard_False;
363     }
364   }
365   
366   if (anIsSolid2 && (!myInnerSol))
367   {
368     if(!SolidTreatment(myShape2, myMapV1, aRootScope.Next()))
369     {
370       return Standard_False;
371     }
372   }
373
374   if (!myInnerSol)
375   {
376     if (!myIsInitS1) // rebuild cached data for 1st shape
377     {
378       myBV1.Clear();
379       myBE1.Clear();
380       myBF1.Clear();
381
382       BoxCalculation (myMapV1, myBV1);
383       BoxCalculation (myMapE1, myBE1);
384       BoxCalculation (myMapF1, myBF1);
385
386       myIsInitS1 = Standard_True;
387     }
388
389     if (!myIsInitS2) // rebuild cached data for 2nd shape
390     {
391       myBV2.Clear();
392       myBE2.Clear();
393       myBF2.Clear();
394
395       BoxCalculation (myMapV2, myBV2);
396       BoxCalculation (myMapE2, myBE2);
397       BoxCalculation (myMapF2, myBF2);
398
399       myIsInitS2 = Standard_True;
400     }
401
402     if (myMapV1.Extent() && myMapV2.Extent())
403     {
404       TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
405       TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
406       myDistRef = DistanceInitiale(V1, V2);
407     }
408     else
409       myDistRef= 1.e30; //szv:!!!
410
411     if(!DistanceMapMap (myMapV1, myMapV2, myBV1, myBV2, aRootScope.Next()))
412     {
413       return Standard_False;
414     }
415     if(!DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2, aRootScope.Next()))
416     {
417       return Standard_False;
418     }
419     if(!DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2, aRootScope.Next()))
420     {
421       return Standard_False;
422     }
423     if(!DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2, aRootScope.Next()))
424     {
425       return Standard_False;
426     }
427     if(!DistanceMapMap (myMapF1, myMapV2, myBF1, myBV2, aRootScope.Next()))
428     {
429       return Standard_False;
430     }
431     if(!DistanceMapMap (myMapE1, myMapE2, myBE1, myBE2, aRootScope.Next()))
432     {
433       return Standard_False;
434     }
435     if(!DistanceMapMap (myMapE1, myMapF2, myBE1, myBF2, aRootScope.Next()))
436     {
437       return Standard_False;
438     }
439     if(!DistanceMapMap (myMapF1, myMapE2, myBF1, myBE2, aRootScope.Next()))
440     {
441       return Standard_False;
442     }
443
444     if (fabs (myDistRef) > myEps)
445     {
446       if(!DistanceMapMap (myMapF1, myMapF2, myBF1, myBF2, aRootScope.Next()))
447       {
448         return Standard_False;
449       }
450     }
451     
452     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
453     Standard_Integer i = 1;
454     for (; i <= mySolutionsShape1.Length(); i++)
455       if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
456       {
457         mySolutionsShape1.Remove(i);
458         mySolutionsShape2.Remove(i);
459       }
460     //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
461     myIsDone = ( mySolutionsShape1.Length() > 0 );
462   }
463
464   return myIsDone;
465 }
466
467 //=======================================================================
468 //function : Value
469 //purpose  : 
470 //=======================================================================
471
472 Standard_Real BRepExtrema_DistShapeShape::Value() const 
473
474   if (!myIsDone)
475     throw StdFail_NotDone("BRepExtrema_DistShapeShape::Value: There's no solution ");
476
477   return myDistRef;
478 }
479
480 //=======================================================================
481 //function : SupportOnShape1
482 //purpose  : 
483 //=======================================================================
484
485 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
486
487   if (!myIsDone)
488     throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
489
490   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
491   switch (sol.SupportKind())
492   {
493     case BRepExtrema_IsVertex : return sol.Vertex();
494     case BRepExtrema_IsOnEdge : return sol.Edge();
495     case BRepExtrema_IsInFace : return sol.Face();
496   }
497   return TopoDS_Shape();
498 }
499
500 //=======================================================================
501 //function : SupportOnShape2
502 //purpose  : 
503 //=======================================================================
504
505 TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const 
506
507   if (!myIsDone)
508     throw StdFail_NotDone("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
509
510   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
511   switch (sol.SupportKind())
512   {
513     case BRepExtrema_IsVertex : return sol.Vertex();
514     case BRepExtrema_IsOnEdge : return sol.Edge();
515     case BRepExtrema_IsInFace : return sol.Face();
516   }
517   return TopoDS_Shape();
518 }
519
520 //=======================================================================
521 //function : ParOnEdgeS1
522 //purpose  : 
523 //=======================================================================
524
525 void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const 
526
527   if (!myIsDone)
528     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution");
529
530   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
531   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
532     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS1: ParOnEdgeS1 is impossible without EDGE");
533
534   sol.EdgeParameter(t);
535 }
536
537 //=======================================================================
538 //function : ParOnEdgeS2
539 //purpose  : 
540 //=======================================================================
541
542 void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N,  Standard_Real& t) const 
543
544   if (!myIsDone)
545     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution");
546
547   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
548   if (sol.SupportKind() != BRepExtrema_IsOnEdge)
549     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnEdgeS2: ParOnEdgeS2 is impossible without EDGE");
550  
551   sol.EdgeParameter(t);
552 }
553
554 //=======================================================================
555 //function : ParOnFaceS1
556 //purpose  : 
557 //=======================================================================
558
559 void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N,  Standard_Real& u,  Standard_Real& v) const 
560
561   if (!myIsDone)
562     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution");
563
564   const BRepExtrema_SolutionElem &sol = mySolutionsShape1.Value(N);
565   if (sol.SupportKind() != BRepExtrema_IsInFace)
566     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS1: ParOnFaceS1 is impossible without FACE");
567   
568   sol.FaceParameter(u, v);
569 }
570
571 //=======================================================================
572 //function : ParOnFaceS2
573 //purpose  : 
574 //=======================================================================
575
576 void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N,  Standard_Real& u, Standard_Real& v) const 
577
578   if (!myIsDone)
579     throw StdFail_NotDone("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution");
580
581   const BRepExtrema_SolutionElem &sol = mySolutionsShape2.Value(N);
582   if (sol.SupportKind() != BRepExtrema_IsInFace)
583     throw BRepExtrema_UnCompatibleShape("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
584   
585   sol.FaceParameter(u, v);
586 }
587
588 //=======================================================================
589 //function : Dump
590 //purpose  : 
591 //=======================================================================
592
593 void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const 
594 {
595   Standard_Integer i;
596   Standard_Real r1,r2;
597   
598   o<< "the distance  value is :  " << Value()<<std::endl;
599   o<< "the number of solutions is :"<<NbSolution()<<std::endl;
600   o<<std::endl;
601   for (i=1;i<=NbSolution();i++)
602   {
603     o<<"solution number "<<i<<": "<< std::endl;
604     o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<std::endl; 
605     o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< std::endl;
606     o<< "the coordinates of  the point on the first shape are: "<<std::endl; 
607     o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<std::endl;
608     o<< "the coordinates of  the point on the second shape are: "<<std::endl; 
609     o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<std::endl;
610     
611     switch (SupportTypeShape1(i))
612     {
613       case BRepExtrema_IsVertex:
614         break;
615       case BRepExtrema_IsOnEdge:
616         ParOnEdgeS1(i,r1);
617         o << "parameter on the first edge :  t= " << r1 << std::endl;
618         break;
619       case BRepExtrema_IsInFace:
620         ParOnFaceS1(i,r1,r2);
621         o << "parameters on the first face :  u= " << r1 << " v=" <<  r2 << std::endl;
622         break;
623     }
624     switch (SupportTypeShape2(i))
625     {
626       case BRepExtrema_IsVertex:
627         break;
628       case BRepExtrema_IsOnEdge:
629         ParOnEdgeS2(i,r1);
630         o << "parameter on the second edge : t=" << r1 << std::endl;
631         break;
632       case BRepExtrema_IsInFace:
633         ParOnFaceS2(i,r1,r2);
634         o << "parameters on the second face : u= " << r1 << " v=" <<  r2 << std::endl;
635         break;
636     }
637     o<<std::endl;
638   } 
639 }