a6bf3b528585070dd8d466b5f21ff55723c8f11c
[occt.git] / src / TopOpeBRep / TopOpeBRep_LineInter.cxx
1 // Created on: 1993-11-10
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1993-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
18 #include <Adaptor2d_Curve2d.hxx>
19 #include <BRepAdaptor_Curve2d.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <Geom_Circle.hxx>
22 #include <Geom_Curve.hxx>
23 #include <Geom_Ellipse.hxx>
24 #include <Geom_Hyperbola.hxx>
25 #include <Geom_Line.hxx>
26 #include <Geom_Parabola.hxx>
27 #include <Geom_TrimmedCurve.hxx>
28 #include <GeomAbs_SurfaceType.hxx>
29 #include <gp_Pnt.hxx>
30 #include <IntPatch_ALine.hxx>
31 #include <IntPatch_ALineToWLine.hxx>
32 #include <IntPatch_GLine.hxx>
33 #include <IntPatch_IType.hxx>
34 #include <IntPatch_Line.hxx>
35 #include <IntPatch_RLine.hxx>
36 #include <IntPatch_SequenceOfLine.hxx>
37 #include <IntPatch_WLine.hxx>
38 #include <IntSurf_Quadric.hxx>
39 #include <Standard_NotImplemented.hxx>
40 #include <Standard_ProgramError.hxx>
41 #include <TCollection_AsciiString.hxx>
42 #include <TopAbs.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Shape.hxx>
45 #include <TopOpeBRep.hxx>
46 #include <TopOpeBRep_Bipoint.hxx>
47 #include <TopOpeBRep_FFTransitionTool.hxx>
48 #include <TopOpeBRep_LineInter.hxx>
49 #include <TopOpeBRep_VPointInter.hxx>
50 #include <TopOpeBRep_VPointInterIterator.hxx>
51 #include <TopOpeBRep_WPointInter.hxx>
52 #include <TopOpeBRepDS_Transition.hxx>
53
54 #include <BRepAdaptor_Surface.hxx>
55
56 #ifdef OCCT_DEBUG
57 extern Standard_Boolean TopOpeBRep_GetcontextALWLNBP(Standard_Integer&);
58 extern Standard_Boolean TopOpeBRep_GettraceCONIC();
59 #endif
60
61 //-----------------------------------------------------------------------
62 static void FUN_ALINETOWLINE (const Handle(IntPatch_ALine)& AL,
63                               const Handle(BRepAdaptor_Surface) surf1,
64                               const Handle(BRepAdaptor_Surface) surf2,
65                               IntPatch_SequenceOfLine& theLines)
66 {
67   Standard_Integer nbpointsmax = 200;
68 #ifdef OCCT_DEBUG
69   Standard_Integer newnbp;
70   if (TopOpeBRep_GetcontextALWLNBP(newnbp)) nbpointsmax = newnbp;
71 #endif
72   IntPatch_ALineToWLine 
73     AToL(surf1,surf2,nbpointsmax);
74
75   AToL.MakeWLine(AL, theLines);
76 }
77
78 //=======================================================================
79 //function : SetLine
80 //purpose  : 
81 //=======================================================================
82
83 void TopOpeBRep_LineInter::SetLine(const Handle(IntPatch_Line)& L,
84                                    const BRepAdaptor_Surface& S1,
85                                    const BRepAdaptor_Surface& S2)
86 {
87   // load line according to its type
88   myIL = L;
89   IntPatch_IType type = L->ArcType();
90   switch (type) {
91   case IntPatch_Analytic :    myTypeLineCurve = TopOpeBRep_ANALYTIC; break;
92   case IntPatch_Restriction : myTypeLineCurve = TopOpeBRep_RESTRICTION; break;
93   case IntPatch_Walking :     myTypeLineCurve = TopOpeBRep_WALKING; break;
94   case IntPatch_Lin :         myTypeLineCurve = TopOpeBRep_LINE; break;
95   case IntPatch_Circle :      myTypeLineCurve = TopOpeBRep_CIRCLE; break;
96   case IntPatch_Ellipse :     myTypeLineCurve = TopOpeBRep_ELLIPSE; break;
97   case IntPatch_Parabola :    myTypeLineCurve = TopOpeBRep_PARABOLA; break;
98   case IntPatch_Hyperbola :   myTypeLineCurve = TopOpeBRep_HYPERBOLA; break;
99   default : 
100     myTypeLineCurve = TopOpeBRep_OTHERTYPE; 
101     SetOK(Standard_False);
102     break;
103   }
104
105   switch (type) {
106   case IntPatch_Analytic :
107     myILA = Handle(IntPatch_ALine)::DownCast (L); break;
108   case IntPatch_Restriction :
109     myILR = Handle(IntPatch_RLine)::DownCast (L); break;
110   case IntPatch_Walking : 
111     myILW = Handle(IntPatch_WLine)::DownCast (L); break;
112   default :  //"geometric" line
113     myILG = Handle(IntPatch_GLine)::DownCast (L); break;
114   }
115
116   // transform an analytic line to a walking line
117   if (myTypeLineCurve == TopOpeBRep_ANALYTIC) {
118     IntPatch_SequenceOfLine aSLin;
119     FUN_ALINETOWLINE(myILA,new BRepAdaptor_Surface(S1),
120                         new BRepAdaptor_Surface(S2), aSLin);
121
122     if(aSLin.Length() > 0)
123       myILW = Handle(IntPatch_WLine)::DownCast(aSLin.Value(1));
124
125     myTypeLineCurve = TopOpeBRep_WALKING;
126   }
127
128   // number of points found on restriction(s)
129   Standard_Integer n = 0;
130   switch (myTypeLineCurve) { 
131   case TopOpeBRep_ANALYTIC :    n = myILA->NbVertex(); break;
132   case TopOpeBRep_RESTRICTION : n = myILR->NbVertex(); break;
133   case TopOpeBRep_WALKING :     n = myILW->NbVertex(); break;
134   case TopOpeBRep_LINE :        n = myILG->NbVertex(); break;
135   case TopOpeBRep_CIRCLE :      n = myILG->NbVertex(); break;
136   case TopOpeBRep_ELLIPSE :     n = myILG->NbVertex(); break;
137   case TopOpeBRep_PARABOLA :    n = myILG->NbVertex(); break; 
138   case TopOpeBRep_HYPERBOLA :   n = myILG->NbVertex(); break;
139   default : 
140     SetOK(Standard_False);
141     break;
142   }
143   myNbVPoint = n;
144
145   // prepare VPoints from intersection points
146   myHAVP = new TopOpeBRep_HArray1OfVPointInter(0,n);
147   for (Standard_Integer i=1;i<=n;i++) {
148     TopOpeBRep_VPointInter& VP = myHAVP->ChangeValue(i);
149     switch (myTypeLineCurve) {
150     case TopOpeBRep_ANALYTIC :    VP.SetPoint(myILA->Vertex(i)); break;
151     case TopOpeBRep_RESTRICTION : VP.SetPoint(myILR->Vertex(i)); break;
152     case TopOpeBRep_WALKING :     VP.SetPoint(myILW->Vertex(i)); break;
153     default :                     VP.SetPoint(myILG->Vertex(i)); break;
154     }
155     VP.Index(i);
156   }
157 }
158
159 //=======================================================================
160 //function : VPoint
161 //purpose  : 
162 //=======================================================================
163
164 const TopOpeBRep_VPointInter& TopOpeBRep_LineInter::VPoint(const Standard_Integer I) const
165 {
166   return myHAVP->Value(I);
167 }
168   
169 //=======================================================================
170 //function : ChangeVPoint
171 //purpose  : 
172 //=======================================================================
173
174 TopOpeBRep_VPointInter& TopOpeBRep_LineInter::ChangeVPoint(const Standard_Integer I)
175 {
176   return myHAVP->ChangeValue(I);
177 }
178   
179 //=======================================================================
180 //function : SetINL
181 //purpose  : 
182 //=======================================================================
183
184 void TopOpeBRep_LineInter::SetINL()
185 {
186   TopOpeBRep_VPointInterIterator VPI(*this);
187   if (!VPI.More()) {
188     myINL = Standard_False;
189     return;
190   }
191   const Standard_Real p0 = VPI.CurrentVP().ParameterOnLine();
192   VPI.Next();
193   if (!VPI.More()) { 
194     myINL = Standard_True;
195     return;
196   }
197   for (; VPI.More(); VPI.Next() ) {
198     const Standard_Real p = VPI.CurrentVP().ParameterOnLine();
199     if ( p != p0 ) {
200       myINL = Standard_False;
201       return;
202     }
203   }
204   myINL = Standard_True;
205 }
206
207 //=======================================================================
208 //function : SetIsVClosed
209 //purpose  : 
210 //=======================================================================
211
212 void TopOpeBRep_LineInter::SetIsVClosed()
213 {
214   if (myINL) {
215     myIsVClosed = Standard_False;
216     return;    
217   }
218
219   /*Standard_Boolean newV = Standard_True;
220   if (!newV) {
221     if (myTypeLineCurve != TopOpeBRep_WALKING) {
222       myIsVClosed = Standard_False;
223       return;
224     }
225   }*/
226   
227   TopOpeBRep_VPointInterIterator VPI(*this);
228   Standard_Integer nV = myNbVPoint;
229   Standard_Real    pmin = RealLast(),pmax = RealFirst();
230   Standard_Integer imin=0, imax = 0; // index of IsOnArc VPoints
231   if (nV >= 2) {
232     for (; VPI.More(); VPI.Next() ) {
233       const TopOpeBRep_VPointInter& P = VPI.CurrentVP();
234       if ( ! P.IsInternal() ) {
235         const Standard_Integer i = VPI.CurrentVPIndex();
236         const Standard_Real p = P.ParameterOnLine();
237         if ( p < pmin ) { imin = i; pmin = p; }
238         if ( p > pmax ) { imax = i; pmax = p; }
239       }
240     }
241     if ( imax == 0 ) {       // no VPoint on restriction found
242       myIsVClosed = Standard_True;
243       return;
244     }
245
246     const TopOpeBRep_VPointInter& P1 = VPoint(imin);
247     const TopOpeBRep_VPointInter& P2 = VPoint(imax);
248
249     const gp_Pnt& pp1 = P1.Value();
250     const gp_Pnt& pp2 = P2.Value();
251
252     const Standard_Real tol1 = P1.Tolerance();
253     const Standard_Real tol2 = P2.Tolerance();
254     const Standard_Real tol = Max(tol1,tol2);
255
256     myIsVClosed = pp1.IsEqual(pp2,tol);
257   }
258   else {
259     SetOK(Standard_False);
260     myIsVClosed = Standard_False;
261   }
262 }
263
264 //=======================================================================
265 //function : SetHasVPonR
266 //purpose  : 
267 //=======================================================================
268
269 void TopOpeBRep_LineInter::SetHasVPonR()
270 {
271   myHasVPonR = Standard_False;
272   TopOpeBRep_VPointInterIterator VPI(*this);
273   for (; VPI.More(); VPI.Next()) {
274     const TopOpeBRep_VPointInter& P = VPI.CurrentVP();
275     if (P.IsOnDomS1() || P.IsOnDomS2()) {
276       myHasVPonR = Standard_True;
277       break;
278     }
279   }
280 }
281
282 //=======================================================================
283 //function : SetVPBounds
284 //purpose  : 
285 //=======================================================================
286
287 void TopOpeBRep_LineInter::SetVPBounds()
288 {
289   myVPF = myVPL = myVPN = 0;
290   myVPBDefined = Standard_True;
291
292   TopOpeBRep_VPointInterIterator VPI(*this);
293   Standard_Integer f = myNbVPoint + 1, l = 0, n = 0;
294   
295   for (; VPI.More(); VPI.Next()) {
296     if (VPI.CurrentVP().Keep()) {
297       n++;
298       const Standard_Integer i = VPI.CurrentVPIndex();
299       if ( i < f ) f = i;
300       if ( i > l ) l = i;
301     }
302   }    
303   
304   myVPF = f; myVPL = l; myVPN = n;  
305 }
306
307 //=======================================================================
308 //function : VPBounds
309 //purpose  : 
310 //=======================================================================
311
312 void TopOpeBRep_LineInter::VPBounds
313 (Standard_Integer& f, Standard_Integer& l, Standard_Integer& n) const
314 {
315   if ( !myVPBDefined ) {
316     TopOpeBRep_LineInter* p = (TopOpeBRep_LineInter*)this; // NYI deconst
317     p->SetOK(Standard_False);
318     f = l = n = 0;
319     return;
320   }
321   f = myVPF;
322   l = myVPL;
323   n = myVPN;
324 }
325
326 //=======================================================================
327 //function : IsPeriodic
328 //purpose  : 
329 //=======================================================================
330
331 Standard_Boolean TopOpeBRep_LineInter::IsPeriodic() const
332 {
333   switch (myTypeLineCurve)
334   {
335     case TopOpeBRep_CIRCLE  :
336     case TopOpeBRep_ELLIPSE : return Standard_True;
337     default:
338       break;
339   }
340   return Standard_False;
341 }
342
343 //=======================================================================
344 //function : Period
345 //purpose  : 
346 //=======================================================================
347
348 Standard_Real TopOpeBRep_LineInter::Period() const
349 {
350   Standard_Real f,l;
351   Bounds(f,l);
352   return (l - f);
353 }
354
355 //=======================================================================
356 //function : Bounds
357 //purpose  : 
358 //=======================================================================
359
360 void TopOpeBRep_LineInter::Bounds(Standard_Real& First,Standard_Real& Last) const
361 {
362   if ( myILG.IsNull() )  {
363     TopOpeBRep_LineInter* p = (TopOpeBRep_LineInter*)this; // NYI deconst
364     p->SetOK(Standard_False);
365     return;
366   }
367   
368   First = 0.; Last = 0.;
369   if ( IsPeriodic() )
370     Last = Curve()->Period();
371   
372   if ( myILG->HasFirstPoint() )
373     First = myILG->FirstPoint().ParameterOnLine();
374
375   if ( myILG->HasLastPoint() )
376     Last = myILG->LastPoint().ParameterOnLine();
377 }
378
379 //=======================================================================
380 //function : HasVInternal
381 //purpose  : 
382 //=======================================================================
383
384 Standard_Boolean TopOpeBRep_LineInter::HasVInternal()
385 {
386   TopOpeBRep_VPointInterIterator VPI(*this);
387   for (; VPI.More(); VPI.Next()) {
388     if (VPI.CurrentVP().IsInternal()) return Standard_True;
389   }
390   return Standard_False;
391 }
392
393
394 //=======================================================================
395 //function : NbWPoint
396 //purpose  : 
397 //=======================================================================
398
399 Standard_Integer TopOpeBRep_LineInter::NbWPoint() const
400 {
401   switch (myTypeLineCurve)
402   {
403     case TopOpeBRep_WALKING : return myILW->NbPnts();
404     default:
405       break;
406   }
407   return 0;
408 }
409
410
411 //=======================================================================
412 //function : WPoint
413 //purpose  : 
414 //=======================================================================
415
416 const TopOpeBRep_WPointInter& TopOpeBRep_LineInter::WPoint(const Standard_Integer IW)
417 {
418   switch (myTypeLineCurve)
419   {
420     case TopOpeBRep_RESTRICTION : myCurrentWP.Set(myILR->Point(IW)); break;
421     case TopOpeBRep_WALKING :     myCurrentWP.Set(myILW->Point(IW)); break;
422     default : break;
423   }
424   return myCurrentWP;
425 }
426
427 //=======================================================================
428 //function : Curve
429 //purpose  : 
430 //=======================================================================
431
432 Handle(Geom_Curve) TopOpeBRep_LineInter::Curve() const 
433 {
434   // Build the 3d curve
435   Handle(Geom_Curve) C3D;
436   switch (myTypeLineCurve) {
437   case TopOpeBRep_LINE : 
438     C3D = new Geom_Line(myILG->Line()); break;
439   case TopOpeBRep_CIRCLE :    
440     C3D = new Geom_Circle(myILG->Circle()); break;
441   case TopOpeBRep_ELLIPSE :   
442     C3D = new Geom_Ellipse(myILG->Ellipse()); break;
443   case TopOpeBRep_PARABOLA :  
444     C3D = new Geom_Parabola(myILG->Parabola()); break;
445   case TopOpeBRep_HYPERBOLA : 
446     C3D = new Geom_Hyperbola(myILG->Hyperbola()); break;
447   default : 
448     TopOpeBRep_LineInter* p = (TopOpeBRep_LineInter*)this; // NYI deconst
449     p->SetOK(Standard_False);
450     break;
451   }
452   return C3D;
453 }
454
455 //=======================================================================
456 //function : Curve
457 //purpose  : 
458 //=======================================================================
459
460 Handle(Geom_Curve) TopOpeBRep_LineInter::Curve
461 (const Standard_Real parmin, const Standard_Real parmax) const 
462 {
463   // Build the trimmed 3d curve
464   Handle(Geom_Curve) C3D = Curve();
465   Handle(Geom_TrimmedCurve) TC3D = new Geom_TrimmedCurve(C3D,parmin,parmax);
466 #ifdef OCCT_DEBUG
467   if ( TopOpeBRep_GettraceCONIC() ) {
468     std::cout<<"TopOpeBRep_LineInter::Curve on a ";
469     TopOpeBRep::Print(myTypeLineCurve,std::cout);std::cout<<std::endl;
470     std::cout<<"  ... Trimmed from "<<parmin<<" to "<<parmax<<std::endl;
471   }
472 #endif
473   return TC3D;
474 }
475
476 //=======================================================================
477 //function : Arc
478 //purpose  : 
479 //=======================================================================
480
481 const TopoDS_Shape& TopOpeBRep_LineInter::Arc() const
482 {
483   if (myTypeLineCurve == TopOpeBRep_RESTRICTION) {
484     if(myILR->IsArcOnS1()) { 
485       const Handle(Adaptor2d_Curve2d)& AHC2D = myILR->ArcOnS1();
486       const BRepAdaptor_Curve2d& BC2DP = *((BRepAdaptor_Curve2d*)AHC2D.get());
487       const TopoDS_Shape& S = BC2DP.Edge();
488       return S;
489     }
490     else { 
491       const Handle(Adaptor2d_Curve2d)& AHC2D = myILR->ArcOnS2();
492       const BRepAdaptor_Curve2d& BC2DP = *((BRepAdaptor_Curve2d*)AHC2D.get());
493       const TopoDS_Shape& S = BC2DP.Edge();
494       return S;
495     }
496   }
497   else
498     return myNullShape;
499 }
500
501 //=======================================================================
502 //function : ArcIsEdge
503 //purpose  : 
504 //=======================================================================
505
506 Standard_Boolean TopOpeBRep_LineInter::ArcIsEdge(const Standard_Integer Index) const
507 {
508   if (myTypeLineCurve == TopOpeBRep_RESTRICTION) {
509     const Standard_Boolean r = myILR->IsArcOnS1();
510     return ( Index == 2 ? !r : r );
511   }
512   return Standard_False;
513 }
514
515 //=======================================================================
516 //function : HasFirstPoint
517 //purpose  : 
518 //=======================================================================
519
520 Standard_Boolean TopOpeBRep_LineInter::HasFirstPoint() const
521 {
522   if (myILG.IsNull())
523     throw Standard_ProgramError("TopOpeBRep_LineInter::HasFirstPoint sur line != GLine");
524   return myILG->HasFirstPoint();
525 }
526
527 //=======================================================================
528 //function : HasLastPoint
529 //purpose  : 
530 //=======================================================================
531
532 Standard_Boolean TopOpeBRep_LineInter::HasLastPoint() const
533 {
534   if (myILG.IsNull())
535     throw Standard_ProgramError("TopOpeBRep_LineInter::HasLastPoint sur line != GLine");
536   return myILG->HasLastPoint();
537 }
538
539 //=======================================================================
540 //function : ComputeFaceFaceTransition
541 //purpose  : 
542 //=======================================================================
543
544 void TopOpeBRep_LineInter::ComputeFaceFaceTransition()
545 {
546   TopAbs_Orientation F1ori = myF1.Orientation();
547   TopAbs_Orientation F2ori = myF2.Orientation();
548   myLineTonF1=TopOpeBRep_FFTransitionTool::ProcessFaceTransition(*this,1,F2ori);
549   myLineTonF2=TopOpeBRep_FFTransitionTool::ProcessFaceTransition(*this,2,F1ori);
550 }
551
552 //=======================================================================
553 //function : FaceFaceTransition
554 //purpose  : 
555 //=======================================================================
556 const TopOpeBRepDS_Transition& TopOpeBRep_LineInter::FaceFaceTransition
557 (const Standard_Integer I) const
558 {
559   if (I == 1) return myLineTonF1;
560   if (I == 2) return myLineTonF2;
561   throw Standard_ProgramError("TopOpeBRep_LineInter::FaceFaceTransition");
562 }
563
564 //=======================================================================
565 //function : DumpType
566 //purpose  : 
567 //=======================================================================
568
569 void TopOpeBRep_LineInter::DumpType()const
570 {
571 #ifdef OCCT_DEBUG
572   TopOpeBRep::Print(myTypeLineCurve,std::cout);
573 #endif
574 }
575
576 //=======================================================================
577 //function : DumpVPoint
578 //purpose  : 
579 //=======================================================================
580
581 void TopOpeBRep_LineInter::DumpVPoint
582 #ifndef OCCT_DEBUG
583 (const Standard_Integer ,
584  const TCollection_AsciiString& ,
585  const TCollection_AsciiString& ) const
586 {
587 #else
588 (const Standard_Integer I,
589  const TCollection_AsciiString& s1,
590  const TCollection_AsciiString& s2) const
591 {
592   const TopOpeBRep_VPointInter& VP = VPoint(I);
593   const gp_Pnt& P = VP.Value();
594   std::cout<<s1;
595   std::cout<<"L"<<Index()<<"P"<<VP.Index();
596   if (VP.Keep()) std::cout<<"K";
597   std::cout<<" "<<P.X()<<" "<<P.Y()<<" "<<P.Z();
598   std::cout<<s2;
599 #endif
600 }
601
602 //=======================================================================
603 //function : DumpBipoint
604 //purpose  : 
605 //=======================================================================
606
607 void TopOpeBRep_LineInter::DumpBipoint
608 #ifndef OCCT_DEBUG
609 (const TopOpeBRep_Bipoint& ,
610  const TCollection_AsciiString& ,
611  const TCollection_AsciiString& ) const
612 {
613 #else
614 (const TopOpeBRep_Bipoint& bip,
615  const TCollection_AsciiString& s1,
616  const TCollection_AsciiString& s2) const
617 {
618   Standard_Integer i1 = bip.I1();
619   Standard_Integer i2 = bip.I2();
620   std::cout<<s1;
621   std::cout<<"("<<i1<<","<<i2<<")";
622   std::cout<<s2;
623 #endif
624 }
625
626 //=======================================================================
627 //function : SetOK
628 //purpose  : 
629 //=======================================================================
630
631 void TopOpeBRep_LineInter::SetOK(const Standard_Boolean B)
632 {
633   myOK = B;
634 }
635
636 //=======================================================================
637 //function : SetTraceIndex
638 //purpose  : 
639 //=======================================================================
640
641 void TopOpeBRep_LineInter::SetTraceIndex(const Standard_Integer exF1,
642                                          const Standard_Integer exF2)
643
644   myexF1 = exF1;
645   myexF2 = exF2;
646 }
647
648 //=======================================================================
649 //function : GetTraceIndex
650 //purpose  : 
651 //=======================================================================
652
653 void TopOpeBRep_LineInter::GetTraceIndex(Standard_Integer& exF1,
654                                          Standard_Integer& exF2)const 
655
656   exF1 = myexF1;
657   exF2 = myexF2;
658 }
659
660 //=======================================================================
661 //function : DumpLineTransitions
662 //purpose  : 
663 //=======================================================================
664 Standard_OStream& TopOpeBRep_LineInter::DumpLineTransitions(Standard_OStream& OS) const
665 {
666 #ifdef OCCT_DEBUG
667   OS<<"transition from f1 / f2 "; TopAbs::Print(myF2.Orientation(),OS);
668   OS<<"transition from f2 / f1 "; TopAbs::Print(myF1.Orientation(),OS);
669 #endif
670   return OS;
671 }