0025418: Debug output to be limited to OCC development environment
[occt.git] / src / TopOpeBRep / TopOpeBRep_ShapeIntersector.cxx
1 // Created on: 1993-05-07
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 #include <TopOpeBRep_ShapeIntersector.ixx>
18
19 #include <TopAbs.hxx>
20 #include <Bnd_Box.hxx>
21 #include <TopOpeBRepTool_box.hxx>
22 #include <TopOpeBRep_define.hxx>
23
24 #ifdef OCCT_DEBUG
25 extern Standard_Boolean TopOpeBRep_GettraceSI(); 
26 extern Standard_Boolean TopOpeBRep_GetcontextFFOR();
27 extern Standard_Integer SAVFFi1; // FacesIntersector
28 extern Standard_Integer SAVFFi2; // FacesIntersector
29 extern void TopOpeBRep_SettraceEEFF(const Standard_Boolean b);
30 extern Standard_Boolean TopOpeBRep_GettraceEEFF(const Standard_Integer e1,const Standard_Integer e2,const Standard_Integer f1,const Standard_Integer f2);
31 void seteeff(const Standard_Boolean b,const Standard_Integer e1,const Standard_Integer e2, const Standard_Integer f1,const Standard_Integer f2)
32 {cout<<"b,e1,e2,f1,f2 : "<<b<<" "<<e1<<","<<e2<<","<<f1<<","<<f2<<endl;TopOpeBRep_SettraceEEFF(b);}
33 void seteefft(const Standard_Integer e1,const Standard_Integer e2, const Standard_Integer f1,const Standard_Integer f2) {seteeff(Standard_True,e1,e2,f1,f2);}
34 void seteefff(const Standard_Integer e1,const Standard_Integer e2, const Standard_Integer f1,const Standard_Integer f2) {seteeff(Standard_False,e1,e2,f1,f2);}
35 #endif
36
37 // modified by NIZHNY-OFV  Thu Apr 18 17:15:38 2002 (S)
38 #include <TopoDS.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Solid.hxx>
41 #include <TopoDS_Shell.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Wire.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_ListOfShape.hxx>
48 #include <TopExp.hxx>
49 #include <gp_Pnt.hxx>
50 #include <gp_Vec.hxx>
51 #include <BRepLib_MakeEdge.hxx>
52 #include <BRepLib_MakeWire.hxx>
53 #include <BRepLib_MakeFace.hxx>
54 #include <BRep_Builder.hxx>
55 #include <BRepAdaptor_Surface.hxx>
56 static Standard_Integer OneShapeIsHalfSpace(const TopoDS_Shape& S1,const TopoDS_Shape& S2);
57 static TopoDS_Solid GetNewSolid(const TopoDS_Shape& S, TopoDS_Face& F);
58 // modified by NIZHNY-OFV  Thu Apr 18 17:16:45 2002 (F)
59
60 //=======================================================================
61 //function : TopOpeBRep_ShapeIntersector
62 //purpose  : 
63 //=======================================================================
64
65 TopOpeBRep_ShapeIntersector::TopOpeBRep_ShapeIntersector()
66 {
67   Reset();
68   myFFIntersector.GetTolerances(myTol1,myTol2);
69   myHBoxTool = FBOX_GetHBoxTool();
70   myFaceScanner.ChangeBoxSort().SetHBoxTool(myHBoxTool);
71   myEdgeScanner.ChangeBoxSort().SetHBoxTool(myHBoxTool);
72 }
73
74 //=======================================================================
75 //function : Reset
76 //purpose  : 
77 //=======================================================================
78
79 void TopOpeBRep_ShapeIntersector::Reset()
80 {
81   myIntersectionDone = Standard_False;
82
83   myFFDone = Standard_False;
84   myFFSameDomain = Standard_False;
85   myEEFFDone = Standard_False;
86   myEFDone = Standard_False;
87   myFEDone = Standard_False;
88   myEEDone = Standard_False;
89
90   myFFInit = Standard_False;
91   myEEFFInit = Standard_False;
92   myEFInit = Standard_False;
93   myFEInit = Standard_False;
94   myEEInit = Standard_False;
95 }
96
97 //=======================================================================
98 //function : Init
99 //purpose  : 
100 //=======================================================================
101
102 void TopOpeBRep_ShapeIntersector::Init
103 (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
104 {
105   Reset();
106   myShape1 = S1;
107   myShape2 = S2;
108 }
109
110 //=======================================================================
111 //function : SetIntersectionDone
112 //purpose  : 
113 //=======================================================================
114
115 void TopOpeBRep_ShapeIntersector::SetIntersectionDone()
116 {
117   myIntersectionDone = (myFFDone || 
118                         myEEFFDone || 
119                         myFEDone || 
120                         myEFDone || 
121                         myEEDone);
122 }
123
124
125 //=======================================================================
126 //function : CurrentGeomShape
127 //purpose  : 
128 //=======================================================================
129
130 const TopoDS_Shape& TopOpeBRep_ShapeIntersector::CurrentGeomShape
131   (const Standard_Integer Index) const
132 {
133   if ( myIntersectionDone ) {
134     if      (myFFDone) {
135       if      ( Index == 1 ) return myFaceScanner.Current();
136       else if ( Index == 2 ) return myFaceExplorer.Current();
137     }
138     else if (myEEFFDone) {
139       if      ( Index == 1 ) return myEdgeScanner.Current();
140       else if ( Index == 2 ) return myEdgeExplorer.Current();
141     }
142     else if (myFEDone) {
143       if      ( Index == 1 ) return myFaceScanner.Current();
144       else if ( Index == 2 ) return myEdgeExplorer.Current();
145     }
146     else if (myEFDone) {
147       if      ( Index == 1 ) return myEdgeScanner.Current();
148       else if ( Index == 2 ) return myFaceExplorer.Current();
149     }
150     else if (myEEDone) {
151       if      ( Index == 1 ) return myEdgeScanner.Current();
152       else if ( Index == 2 ) return myEdgeExplorer.Current();
153     }
154   }
155
156   Standard_Failure::Raise("CurrentGeomShape : no intersection");
157   TopoDS_Shape* bid = new TopoDS_Shape();
158   return *bid;
159 }
160 //modified by NIZNHY-PKV Fri Sep 24 11:02:59 1999 from
161 //=======================================================================
162 //function : RejectedFaces
163 //purpose  : 
164 //=======================================================================
165 void TopOpeBRep_ShapeIntersector::RejectedFaces (const TopoDS_Shape& anObj,
166                                                  const TopoDS_Shape& aReference,
167                                                  TopTools_ListOfShape& aListOfShape)
168 {
169
170   Standard_Integer isHalfSpace = OneShapeIsHalfSpace( anObj, aReference );
171   if( isHalfSpace != 0 )
172     {
173       TopoDS_Face newRejectFace;
174       TopoDS_Solid newSolid;
175       aListOfShape.Clear();
176       
177       if( isHalfSpace == 1 )
178         {
179           newSolid = GetNewSolid( anObj, newRejectFace );
180           Init( newSolid, aReference );
181
182           TopAbs_ShapeEnum tscann = TopAbs_SOLID;
183           TopAbs_ShapeEnum texplo = TopAbs_FACE;
184           myFaceScanner.Clear();
185           myFaceScanner.AddBoxesMakeCOB( aReference, tscann );
186           myFaceExplorer.Init( newSolid, texplo );
187   
188           for(; myFaceExplorer.More(); myFaceExplorer.Next())
189             {
190               TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
191               if(!aBS.Compare(myFaceExplorer.Current()).More())
192                 {
193                   const TopoDS_Shape& aS=myFaceExplorer.Current();
194                   aListOfShape.Append (aS);
195                 }
196             }
197
198           texplo = TopAbs_EDGE;
199           myFaceScanner.Clear();
200           myFaceScanner.AddBoxesMakeCOB( aReference, tscann );
201           myFaceExplorer.Init( newSolid, texplo );
202
203           for(; myFaceExplorer.More(); myFaceExplorer.Next())
204             {
205               TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
206               if(!aBS.Compare(myFaceExplorer.Current()).More())
207                 {
208                   const TopoDS_Shape& aS=myFaceExplorer.Current();
209                   aListOfShape.Append (aS);
210                 }
211             }
212         }
213       else
214         {
215           newSolid = GetNewSolid( aReference, newRejectFace );
216           Init( anObj, newSolid );
217
218           TopAbs_ShapeEnum tscann = TopAbs_SOLID;
219           TopAbs_ShapeEnum texplo = TopAbs_FACE;
220           myFaceScanner.Clear();
221           myFaceScanner.AddBoxesMakeCOB( newSolid, tscann );
222           myFaceExplorer.Init( anObj, texplo);
223   
224           for(; myFaceExplorer.More(); myFaceExplorer.Next())
225             {
226               TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
227               if(!aBS.Compare(myFaceExplorer.Current()).More())
228                 {
229                   const TopoDS_Shape& aS=myFaceExplorer.Current();
230                   aListOfShape.Append (aS);
231                 }
232             }
233
234           texplo = TopAbs_EDGE;
235           myFaceScanner.Clear();
236           myFaceScanner.AddBoxesMakeCOB( newSolid, tscann );
237           myFaceExplorer.Init( anObj, texplo );
238
239           for(; myFaceExplorer.More(); myFaceExplorer.Next())
240             {
241               TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
242               if(!aBS.Compare(myFaceExplorer.Current()).More())
243                 {
244                   const TopoDS_Shape& aS=myFaceExplorer.Current();
245                   aListOfShape.Append (aS);
246                 }
247             }
248         }
249       // remove all shapes of < newRejectFace > from list
250       TopExp_Explorer ExpRF(newRejectFace, TopAbs_EDGE);
251       for(; ExpRF.More(); ExpRF.Next() )
252         {
253           const TopoDS_Edge& edgef = TopoDS::Edge( ExpRF.Current() );
254           TopTools_ListIteratorOfListOfShape it( aListOfShape );
255           for(; it.More(); it.Next() )
256             {
257               const TopoDS_Shape& shape = it.Value();
258
259               if( shape.ShapeType() != TopAbs_EDGE )
260                 continue;
261
262               const TopoDS_Edge& edgel = TopoDS::Edge( shape );
263               if( edgef.IsSame( edgel ) )
264                 {
265                   aListOfShape.Remove(it);
266                   break;
267                 }
268             }
269         }
270       TopTools_ListIteratorOfListOfShape it( aListOfShape );
271       for(; it.More(); it.Next() )
272         {
273           const TopoDS_Shape& shape = it.Value();
274
275           if( shape.ShapeType() != TopAbs_FACE )
276             continue;
277
278           const TopoDS_Face& facel = TopoDS::Face( shape );
279           if( facel.IsSame( newRejectFace ) )
280             {
281               aListOfShape.Remove(it);
282               break;
283             }
284         }
285       
286       Init(anObj, aReference);
287       return;
288     }
289
290   Init(anObj, aReference);
291
292   aListOfShape.Clear(); 
293   //find faces to reject
294   
295   TopAbs_ShapeEnum tscann = TopAbs_SOLID;
296   TopAbs_ShapeEnum texplo = TopAbs_FACE;
297   myFaceScanner.Clear();
298   myFaceScanner.AddBoxesMakeCOB(aReference,tscann);
299   myFaceExplorer.Init(anObj,texplo);
300   
301   for(; myFaceExplorer.More(); myFaceExplorer.Next()) {
302     TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
303     if(!aBS.Compare(myFaceExplorer.Current()).More()) {
304       const TopoDS_Shape& aS=myFaceExplorer.Current();
305       aListOfShape.Append (aS);
306     }
307   }
308
309   //modified by NIZHNY-MZV  Wed Apr  5 09:45:17 2000
310   texplo = TopAbs_EDGE;
311   myFaceScanner.Clear();
312   myFaceScanner.AddBoxesMakeCOB(aReference,tscann);
313   myFaceExplorer.Init(anObj,texplo);
314
315   for(; myFaceExplorer.More(); myFaceExplorer.Next()) {
316     TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
317     if(!aBS.Compare(myFaceExplorer.Current()).More()) {
318       const TopoDS_Shape& aS=myFaceExplorer.Current();
319       aListOfShape.Append (aS);
320     }
321   }
322
323   //modified by NIZHNY-MZV  Wed Apr  5 09:45:17 2000
324 /*  texplo = TopAbs_VERTEX;
325   myFaceScanner.Clear();
326   myFaceScanner.AddBoxesMakeCOB(aReference,tscann);
327   myFaceExplorer.Init(anObj,texplo);
328
329   for(; myFaceExplorer.More(); myFaceExplorer.Next()) {
330     TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort();
331     if(!aBS.Compare(myFaceExplorer.Current()).More()) {
332       const TopoDS_Shape& aS=myFaceExplorer.Current();
333       aListOfShape.Append (aS);
334     }
335   }
336 */
337 }
338 //modified by NIZNHY-PKV Fri Sep 24 11:03:02 1999 to
339
340
341
342
343 //=======================================================================
344 //function : InitIntersection
345 //purpose  : 
346 //=======================================================================
347
348   void TopOpeBRep_ShapeIntersector::InitIntersection (const TopoDS_Shape& S1, const TopoDS_Shape& S2)
349 {
350   Init(S1,S2);
351
352   InitFFIntersection();
353   if ( MoreFFCouple() ) return;
354
355   InitFEIntersection();
356   if ( MoreFECouple() ) return;
357
358   InitEFIntersection();
359   if ( MoreEFCouple() ) return;
360 }
361
362
363 //=======================================================================
364 //function : InitIntersection
365 //purpose  : 
366 //=======================================================================
367
368 void TopOpeBRep_ShapeIntersector::InitIntersection
369   (const TopoDS_Shape& S1, const TopoDS_Shape& S2,
370    const TopoDS_Face&  F1, const TopoDS_Face&  F2)
371 {
372   Init(S1,S2);
373
374   myEEFace1 = F1;
375   myEEFace2 = F2;
376
377   InitEEIntersection();
378 }
379
380
381 //=======================================================================
382 //function : MoreIntersection
383 //purpose  : 
384 //=======================================================================
385
386 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreIntersection() const
387 {
388   Standard_Boolean res = myIntersectionDone;
389
390 #ifdef OCCT_DEBUG
391   if (TopOpeBRep_GettraceSI() && res) {
392     if      ( myFFDone )   cout<<"FF : ";
393     else if ( myEEFFDone ) cout<<"    EE : ";
394     DumpCurrent(1);
395     DumpCurrent(2);
396     if      ( myFFDone && myFFSameDomain ) cout<<"(FF SameDomain)";
397     else if ( myEEFFDone )                 cout<<"(EE of FF SameDomain)";
398     else if ( myEEDone )                   cout<<"EE : ";
399     cout<<endl;
400     if (myEEFFDone) {
401       Standard_Integer ie1 = myEdgeScanner.Index();
402       Standard_Integer ie2 = myEdgeExplorer.Index();
403       Standard_Integer if1 = myFaceScanner.Index();
404       Standard_Integer if2 = myFaceExplorer.Index();
405       cout<<"    trc teeff 1 "<<ie1<<" "<<ie2<<" "<<if1<<" "<<if2<<"; # ie1 ie2 if1 if2"<<endl;
406       Standard_Boolean b = TopOpeBRep_GettraceEEFF(ie1,ie2,if1,if2);
407       if (b) seteefft(ie1,ie2,if1,if2);
408       else   seteefff(ie1,ie2,if1,if2);
409     }
410   }    
411 #endif
412
413   return res;
414 }
415
416
417 //=======================================================================
418 //function : DumpCurrent
419 //purpose  : 
420 //=======================================================================
421
422 #ifdef OCCT_DEBUG
423 void TopOpeBRep_ShapeIntersector::DumpCurrent(const Standard_Integer K) const
424 {
425   if      ( myFFDone ) {
426     if      ( K == 1 ) myFaceScanner.DumpCurrent(cout);
427     else if ( K == 2 ) myFaceExplorer.DumpCurrent(cout);
428   }
429   else if ( myEEFFDone ) {
430     if      ( K == 1 ) myEdgeScanner.DumpCurrent(cout);
431     else if ( K == 2 ) myEdgeExplorer.DumpCurrent(cout);
432   }
433   else if ( myFEDone ) {
434     if      ( K == 1 ) myFaceScanner.DumpCurrent(cout);
435     else if ( K == 2 ) myEdgeExplorer.DumpCurrent(cout);
436   }
437   else if ( myEFDone ) {
438     if      ( K == 1 ) myEdgeScanner.DumpCurrent(cout);
439     else if ( K == 2 ) myFaceExplorer.DumpCurrent(cout);
440   }
441   else if ( myEEDone ) {
442     if      ( K == 1 ) myEdgeScanner.DumpCurrent(cout);
443     else if ( K == 2 ) myEdgeExplorer.DumpCurrent(cout);
444   }
445 }
446 #else
447 void TopOpeBRep_ShapeIntersector::DumpCurrent(const Standard_Integer) const {}
448 #endif
449
450 //=======================================================================
451 //function : Index
452 //purpose  : 
453 //=======================================================================
454
455 #ifdef OCCT_DEBUG
456 Standard_Integer TopOpeBRep_ShapeIntersector::Index
457 (const Standard_Integer K)const
458 {
459   Standard_Integer i = 0;
460
461   if      ( myFFDone ) {
462     if      ( K == 1 ) i = myFaceScanner.Index();
463     else if ( K == 2 ) i = myFaceExplorer.Index();
464   }
465   else if ( myEEFFDone ) {
466     if      ( K == 1 ) i = myEdgeScanner.Index();
467     else if ( K == 2 ) i = myEdgeExplorer.Index();
468   }
469   else if ( myFEDone ) {
470     if      ( K == 1 ) i = myFaceScanner.Index();
471     else if ( K == 2 ) i = myEdgeExplorer.Index();
472   }
473   else if ( myEFDone ) {
474     if      ( K == 1 ) i = myEdgeScanner.Index();
475     else if ( K == 2 ) i = myFaceExplorer.Index();
476   }
477   else if ( myEEDone ) {
478     if      ( K == 1 ) i = myEdgeScanner.Index();
479     else if ( K == 2 ) i = myEdgeExplorer.Index();
480   }
481   return i;
482 }
483 #else
484 Standard_Integer TopOpeBRep_ShapeIntersector::Index (const Standard_Integer)const
485 {
486   return 0;
487 }
488 #endif
489
490
491 //=======================================================================
492 //function : NextIntersection
493 //purpose  : 
494 //=======================================================================
495
496 void TopOpeBRep_ShapeIntersector::NextIntersection()
497 {
498   myIntersectionDone = Standard_False;
499
500   if (myFFSameDomain) {
501     // precedant etat du More() : 2 faces samedomain
502     myFFDone = Standard_False;
503     myFFSameDomain = Standard_False;
504     InitEEFFIntersection();
505     FindEEFFIntersection();
506     if ( !myIntersectionDone ) {
507       NextFFCouple();
508       FindFFIntersection();
509     }
510   }
511   else if (myFFDone) {
512     NextFFCouple();
513     FindFFIntersection();
514   }
515   else if ( myEEFFDone ) {
516     NextEEFFCouple();
517     FindEEFFIntersection();
518     if ( !myIntersectionDone ) {
519       NextFFCouple();
520       FindFFIntersection();
521     }
522   }
523   else if ( myFEDone ) {
524     NextFECouple();
525     FindFEIntersection();
526   }
527   else if ( myEFDone ) {
528     NextEFCouple();
529     FindEFIntersection();
530   }
531    else if ( myEEDone ) {
532     NextEECouple();
533     FindEEIntersection();
534   }
535
536   if ( !myIntersectionDone ) {
537     InitFFIntersection();
538   }
539     
540   if ( !myIntersectionDone ) {
541     InitFEIntersection();
542   }
543     
544   if ( !myIntersectionDone ) {
545     InitEFIntersection();
546   }
547
548   if ( !myIntersectionDone ) {
549     if ( !myEEFace1.IsNull() && !myEEFace2.IsNull() ) {
550       InitEEIntersection();
551     }
552   }
553
554 }
555
556
557 // ========
558 // FFFFFFFF
559 // ========
560
561
562 //=======================================================================
563 //function : InitFFIntersection
564 //purpose  : 
565 //=======================================================================
566
567 void TopOpeBRep_ShapeIntersector::InitFFIntersection()
568 {
569  if ( !myFFInit) { 
570    TopAbs_ShapeEnum tscann = TopAbs_FACE;
571    TopAbs_ShapeEnum texplo = TopAbs_FACE;
572    myFaceScanner.Clear();
573    myFaceScanner.AddBoxesMakeCOB(myShape1,tscann);
574    myFaceExplorer.Init(myShape2,texplo);
575    myFaceScanner.Init(myFaceExplorer);
576    FindFFIntersection();
577  }
578  myFFInit = Standard_True;
579 }
580
581
582 //=======================================================================
583 //function : FindFFIntersection
584 //purpose  : 
585 //=======================================================================
586
587 void TopOpeBRep_ShapeIntersector::FindFFIntersection()
588 {
589   myFFDone = Standard_False;
590   myFFSameDomain = Standard_False ;
591
592   while ( MoreFFCouple() ) {
593
594     // The two candidate intersecting GeomShapes GS1,GS2 and their types t1,t2
595     const TopoDS_Shape& GS1 = myFaceScanner.Current();
596     const TopoDS_Shape& GS2 = myFaceExplorer.Current();
597
598 #ifdef OCCT_DEBUG
599     SAVFFi1 = myFaceScanner.Index(); SAVFFi2 = myFaceExplorer.Index(); 
600     if (TopOpeBRep_GettraceSI()) {
601       cout<<"?? FF : ";
602       myFaceScanner.DumpCurrent(cout); myFaceExplorer.DumpCurrent(cout);
603       cout<<endl;
604     }    
605 #endif
606
607     const TopOpeBRepTool_BoxSort& BS = myFaceScanner.BoxSort();
608     const Bnd_Box& B1 = BS.Box(GS1);
609     const Bnd_Box& B2 = BS.Box(GS2);
610     myFFIntersector.Perform(GS1,GS2,B1,B2);
611     Standard_Boolean ok = myFFIntersector.IsDone(); //xpu210998
612     if (!ok) {
613       NextFFCouple();
614       continue;
615     }
616
617     myFFSameDomain = myFFIntersector.SameDomain();
618
619     if (myFFSameDomain) {
620       myFFDone = Standard_True;
621       break;
622     }
623     else {
624       myFFDone = ! (myFFIntersector.IsEmpty());
625       
626       // update face/face intersection tolerances
627       if (myFFDone) {
628         Standard_Real tol1,tol2;
629         myFFIntersector.GetTolerances(tol1,tol2);
630         myTol1 = Max(myTol1,tol1); myTol2 = Max(myTol2,tol2);
631       }
632       
633       if ( myFFDone ) {
634         break;
635       }
636     }
637
638     NextFFCouple();
639   }
640
641   SetIntersectionDone();
642 }
643
644
645 //=======================================================================
646 //function : MoreFFCouple
647 //purpose  : 
648 //=======================================================================
649
650 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreFFCouple() const
651 {
652   Standard_Boolean more1 = myFaceScanner.More();
653   Standard_Boolean more2 = myFaceExplorer.More();
654   return (more1 && more2);
655 }
656
657
658 //=======================================================================
659 //function : NextFFCouple
660 //purpose  : 
661 //=======================================================================
662
663 void TopOpeBRep_ShapeIntersector::NextFFCouple()
664 {
665   myFaceScanner.Next();
666   Standard_Boolean b1,b2;
667
668   b1 = (!myFaceScanner.More());
669   b2 = (myFaceExplorer.More());
670   while ( b1 && b2 ) {
671     myFaceExplorer.Next();
672     myFaceScanner.Init(myFaceExplorer);
673     b1 = (!myFaceScanner.More());
674     b2 = (myFaceExplorer.More());
675   }
676
677 }
678
679
680 // ========
681 // EEFFEEFF
682 // ========
683
684
685 //=======================================================================
686 //function : InitEEFFIntersection
687 //purpose  : 
688 //=======================================================================
689
690 void TopOpeBRep_ShapeIntersector::InitEEFFIntersection()
691 {
692   // prepare exploration of the edges of the two current SameDomain faces 
693   TopoDS_Shape face1 = myFaceScanner.Current(); // -26-08-96
694   TopoDS_Shape face2 = myFaceExplorer.Current(); // -26-08-96
695
696 #ifdef OCCT_DEBUG
697   if (TopOpeBRep_GetcontextFFOR()) {
698     face1.Orientation(TopAbs_FORWARD); //-05/07
699     face2.Orientation(TopAbs_FORWARD); //-05/07
700     cout<<"ctx : InitEEFFIntersection : faces FORWARD"<<endl;
701   }
702 #endif
703
704   const TopOpeBRepTool_BoxSort& BS = myFaceScanner.BoxSort();
705   const Bnd_Box& B1 = BS.Box(face1);
706   const Bnd_Box& B2 = BS.Box(face2);
707   myEEIntersector.SetFaces(face1,face2,B1,B2);
708   
709   TopAbs_ShapeEnum tscann = TopAbs_EDGE;
710   TopAbs_ShapeEnum texplo = TopAbs_EDGE;
711   myEdgeScanner.Clear();
712   myEdgeScanner.AddBoxesMakeCOB(face1,tscann);
713   myEdgeExplorer.Init(face2,texplo);
714   myEdgeScanner.Init(myEdgeExplorer);
715   
716   myEEFFInit = Standard_True;
717 }
718
719
720 //=======================================================================
721 //function : FindEEFFIntersection
722 //purpose  : 
723 //=======================================================================
724
725 void TopOpeBRep_ShapeIntersector::FindEEFFIntersection()
726 {
727   myEEFFDone = Standard_False;
728   while ( MoreEEFFCouple() ) {
729     const TopoDS_Shape& GS1 = myEdgeScanner.Current();
730     const TopoDS_Shape& GS2 = myEdgeExplorer.Current();
731     myEEIntersector.Perform(GS1,GS2);
732
733 #ifdef OCCT_DEBUG
734     if (TopOpeBRep_GettraceSI() && myEEIntersector.IsEmpty()) {
735       cout<<"    EE : ";
736       myEdgeScanner.DumpCurrent(cout);
737       myEdgeExplorer.DumpCurrent(cout);
738       cout<<"(EE of FF SameDomain)";
739       cout<<" : EMPTY INTERSECTION";
740       cout<<endl;
741     }    
742 #endif
743
744     myEEFFDone = ! (myEEIntersector.IsEmpty());
745     if (myEEFFDone) break;
746     else NextEEFFCouple();
747   }
748   SetIntersectionDone();
749 }
750
751
752 //=======================================================================
753 //function : MoreEEFFCouple
754 //purpose  : 
755 //=======================================================================
756
757 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreEEFFCouple() const
758 {
759   Standard_Boolean more1 = myEdgeScanner.More();
760   Standard_Boolean more2 = myEdgeExplorer.More();
761   return (more1 && more2);
762 }
763
764
765 //=======================================================================
766 //function : NextEEFFCouple
767 //purpose  : 
768 //=======================================================================
769
770 void TopOpeBRep_ShapeIntersector::NextEEFFCouple()
771 {
772   myEdgeScanner.Next();
773   while ( ! myEdgeScanner.More() && myEdgeExplorer.More() ) {
774     myEdgeExplorer.Next();
775     myEdgeScanner.Init(myEdgeExplorer);
776   }
777 }
778
779
780 // ========
781 // FEFEFEFE
782 // ========
783
784
785 //=======================================================================
786 //function : InitFEIntersection
787 //purpose  : 
788 //=======================================================================
789
790 void TopOpeBRep_ShapeIntersector::InitFEIntersection()
791 {
792  if ( !myFEInit) { 
793    TopAbs_ShapeEnum tscann = TopAbs_FACE;
794    TopAbs_ShapeEnum texplo = TopAbs_EDGE;
795    myFaceScanner.Clear(); 
796    myFaceScanner.AddBoxesMakeCOB(myShape1,tscann);
797    myEdgeExplorer.Init(myShape2,texplo,TopAbs_FACE); // NYI defaut de spec
798    myFaceScanner.Init(myEdgeExplorer);
799    FindFEIntersection();
800  }
801  myFEInit = Standard_True;
802 }
803
804
805 //=======================================================================
806 //function : FindFEIntersection
807 //purpose  : 
808 //=======================================================================
809
810 void TopOpeBRep_ShapeIntersector::FindFEIntersection()
811 {
812   myFEDone = Standard_False;
813   while ( MoreFECouple() ) {
814     const TopoDS_Shape& GS1 = myFaceScanner.Current();
815     const TopoDS_Shape& GS2 = myEdgeExplorer.Current();
816     myFEIntersector.Perform(GS1,GS2);
817     myFEDone = ! (myFEIntersector.IsEmpty());
818     if (myFEDone) break;
819     else NextFECouple();
820   }
821   SetIntersectionDone();
822 }
823
824
825 //=======================================================================
826 //function : MoreFECouple
827 //purpose  : 
828 //=======================================================================
829
830 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreFECouple() const
831 {
832   Standard_Boolean more1 = myFaceScanner.More();
833   Standard_Boolean more2 = myEdgeExplorer.More();
834   return (more1 && more2);
835 }
836
837
838 //=======================================================================
839 //function : NextFECouple
840 //purpose  : 
841 //=======================================================================
842
843 void TopOpeBRep_ShapeIntersector::NextFECouple()
844 {
845   myFaceScanner.Next();
846   while ( ! myFaceScanner.More() && myEdgeExplorer.More() ) {
847     myEdgeExplorer.Next();
848     myFaceScanner.Init(myEdgeExplorer);
849   }
850 }
851
852
853 // ========
854 // EFEFEFEF
855 // ========
856
857
858 //=======================================================================
859 //function : InitEFIntersection
860 //purpose  : 
861 //=======================================================================
862
863 void TopOpeBRep_ShapeIntersector::InitEFIntersection()
864 {
865  if ( !myEFInit) { 
866    TopAbs_ShapeEnum tscann = TopAbs_EDGE;
867    TopAbs_ShapeEnum texplo = TopAbs_FACE;
868    myEdgeScanner.Clear(); 
869    myEdgeScanner.AddBoxesMakeCOB(myShape1,tscann, TopAbs_FACE); // NYI defaut de spec
870    myFaceExplorer.Init(myShape2,texplo);
871    myEdgeScanner.Init(myFaceExplorer);
872    FindEFIntersection();
873  }
874  myEFInit = Standard_True;
875
876  
877 //=======================================================================
878 //function : FindEFIntersection
879 //purpose  : 
880 //=======================================================================
881
882 void TopOpeBRep_ShapeIntersector::FindEFIntersection()
883 {
884   myEFDone = Standard_False;
885   while ( MoreEFCouple() ) {
886     const TopoDS_Shape& GS1 = myEdgeScanner.Current();
887     const TopoDS_Shape& GS2 = myFaceExplorer.Current();
888     myFEIntersector.Perform(GS2,GS1);
889     myEFDone = ! (myFEIntersector.IsEmpty());
890     if (myEFDone) break;
891     else NextEFCouple();
892   }
893   SetIntersectionDone();
894 }
895
896
897 //=======================================================================
898 //function : MoreEFCouple
899 //purpose  : 
900 //=======================================================================
901
902 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreEFCouple() const
903 {
904   Standard_Boolean more1 = myEdgeScanner.More();
905   Standard_Boolean more2 = myFaceExplorer.More();
906   return (more1 && more2);
907 }
908
909
910 //=======================================================================
911 //function : NextEFCouple
912 //purpose  : 
913 //=======================================================================
914
915 void TopOpeBRep_ShapeIntersector::NextEFCouple()
916 {
917   myEdgeScanner.Next();
918   while ( ! myEdgeScanner.More() && myFaceExplorer.More() ) {
919     myFaceExplorer.Next();
920     myEdgeScanner.Init(myFaceExplorer);
921   }
922 }
923
924 // ========
925 // EEEEEEEE
926 // ========
927
928 //=======================================================================
929 //function : InitEEIntersection
930 //purpose  : 
931 //=======================================================================
932
933 void TopOpeBRep_ShapeIntersector::InitEEIntersection()
934 {
935   if ( ! myEEInit ) {
936     TopoDS_Shape face1 = myEEFace1.Oriented(TopAbs_FORWARD);
937     TopoDS_Shape face2 = myEEFace2.Oriented(TopAbs_FORWARD);
938     const TopOpeBRepTool_BoxSort& BS = myFaceScanner.BoxSort();
939     const Bnd_Box& B1 = BS.Box(face1);
940     const Bnd_Box& B2 = BS.Box(face2);
941     myEEIntersector.SetFaces(face1,face2,B1,B2);
942
943     TopAbs_ShapeEnum tscann = TopAbs_EDGE;
944     TopAbs_ShapeEnum texplo = TopAbs_EDGE;
945     myEdgeScanner.Clear();
946     myEdgeScanner.AddBoxesMakeCOB(myShape1,tscann);
947     myEdgeExplorer.Init(myShape2,texplo);
948     myEdgeScanner.Init(myEdgeExplorer);
949     FindEEIntersection();
950   }
951   myEEInit = Standard_True;
952 }
953
954
955 //=======================================================================
956 //function : FindEEIntersection
957 //purpose  : 
958 //=======================================================================
959
960 void TopOpeBRep_ShapeIntersector::FindEEIntersection()
961 {
962   myEEDone = Standard_False;
963   while ( MoreEECouple() ) {
964     const TopoDS_Shape& GS1 = myEdgeScanner.Current();
965     const TopoDS_Shape& GS2 = myEdgeExplorer.Current();
966     myEEIntersector.Perform(GS1,GS2);
967     myEEDone = ! (myEEIntersector.IsEmpty());
968     if (myEEDone) break;
969     else NextEECouple();
970   }
971   SetIntersectionDone();
972 }
973
974
975 //=======================================================================
976 //function : MoreEECouple
977 //purpose  : 
978 //=======================================================================
979
980 Standard_Boolean TopOpeBRep_ShapeIntersector::MoreEECouple() const
981 {
982   Standard_Boolean more1 = myEdgeScanner.More();
983   Standard_Boolean more2 = myEdgeExplorer.More();
984   return (more1 && more2);
985 }
986
987
988 //=======================================================================
989 //function : NextEECouple
990 //purpose  : 
991 //=======================================================================
992
993 void TopOpeBRep_ShapeIntersector::NextEECouple()
994 {
995   myEdgeScanner.Next();
996   while ( ! myEdgeScanner.More() && myEdgeExplorer.More() ) {
997     myEdgeExplorer.Next();
998     myEdgeScanner.Init(myEdgeExplorer);
999   }
1000 }
1001
1002
1003 //=======================================================================
1004 //function : Shape
1005 //purpose  : 
1006 //=======================================================================
1007
1008 const TopoDS_Shape& TopOpeBRep_ShapeIntersector::Shape
1009   ( const Standard_Integer Index )const
1010 {
1011   if      ( Index == 1 ) return myShape1;
1012   else if ( Index == 2 ) return myShape2;
1013
1014   Standard_Failure::Raise("ShapeIntersector : no shape");
1015   TopoDS_Shape* bid = new TopoDS_Shape();
1016   return *bid;
1017 }
1018
1019
1020 //=======================================================================
1021 //function : ChangeFacesIntersector
1022 //purpose  : 
1023 //=======================================================================
1024
1025 TopOpeBRep_FacesIntersector& 
1026 TopOpeBRep_ShapeIntersector::ChangeFacesIntersector()
1027 { return myFFIntersector; }
1028
1029
1030 //=======================================================================
1031 //function : ChangeEdgesIntersector
1032 //purpose  : 
1033 //=======================================================================
1034
1035 TopOpeBRep_EdgesIntersector& 
1036 TopOpeBRep_ShapeIntersector::ChangeEdgesIntersector()
1037 { return myEEIntersector; }
1038
1039
1040 //=======================================================================
1041 //function : ChangeFaceEdgeIntersector
1042 //purpose  : 
1043 //=======================================================================
1044
1045 TopOpeBRep_FaceEdgeIntersector& 
1046 TopOpeBRep_ShapeIntersector::ChangeFaceEdgeIntersector()
1047 { return myFEIntersector; }
1048
1049
1050 //=======================================================================
1051 //function : GetTolerances
1052 //purpose  : 
1053 //=======================================================================
1054
1055 void TopOpeBRep_ShapeIntersector::GetTolerances(Standard_Real& tol1,
1056                                                 Standard_Real& tol2)const
1057 { tol1 = myTol1; tol2 = myTol2; }
1058
1059
1060
1061
1062 //=======================================================================
1063 //function : IsHalfSpaceShape
1064 //purpose  : tries to define if one of solids is a half space object
1065 //           returns:
1066 //                    0 - no half spaces ( default )
1067 //                    1 - half space is S1
1068 //                    2 - half space is S2
1069 //=======================================================================
1070 static Standard_Integer OneShapeIsHalfSpace(const TopoDS_Shape& S1,const TopoDS_Shape& S2)
1071 {
1072   Standard_Integer result = 0;
1073
1074   if( S1.ShapeType() == TopAbs_SOLID && S2.ShapeType() == TopAbs_SOLID )
1075     {
1076       TopExp_Explorer ExpSol1(S1, TopAbs_FACE);
1077       TopExp_Explorer ExpSol2(S2, TopAbs_FACE);
1078       Standard_Integer NbFacesSol1 = 0;
1079       Standard_Integer NbFacesSol2 = 0;
1080
1081       for(; ExpSol1.More(); ExpSol1.Next() )
1082         NbFacesSol1++;
1083
1084       for(; ExpSol2.More(); ExpSol2.Next() )
1085         NbFacesSol2++;
1086
1087       if( NbFacesSol1 == 0 || NbFacesSol2 == 0 )  // strange solids!!!
1088         return result;
1089       if( NbFacesSol1 == 1 && NbFacesSol2 == 1 )  // both shapes are half spaces ???
1090         return result;
1091
1092       if( (NbFacesSol1 == 1 && NbFacesSol2 >= 2) || (NbFacesSol2 == 1 && NbFacesSol1 >= 2) )
1093         {
1094           // if one solid has shell consisted of only a face but other one has valid closed
1095           // shell we can detect current boolean operation as operation with half space object.
1096           // if shell of second solid is not valid too we cann't detect what kind of objects
1097           // we try to perform. in this case we do nothing and just return. 
1098
1099           // but before we must avoid shperes, toruses and solids with a face biult on spherical surfaces
1100           // of revolution (SSRFS) - solids with shell of one face:
1101           // sphere (U: 0, 2PI) (V: -PI/2, PI/2),
1102           // torus  (U: 0, 2PI) (V: 0, 2PI).
1103           // SSRFS  (U period = (PI), 2PI) (V period = (PI), 2PI)
1104           // these solids are not halfspaces.
1105
1106           TopExp_Explorer SolidExplorer;
1107           TopoDS_Face testFace;
1108
1109           if( NbFacesSol1 == 1 )
1110             {
1111               for( SolidExplorer.Init(S1, TopAbs_FACE); SolidExplorer.More(); SolidExplorer.Next() )
1112                 testFace = TopoDS::Face( SolidExplorer.Current() );
1113             }
1114           else
1115             {
1116               for( SolidExplorer.Init(S2, TopAbs_FACE); SolidExplorer.More(); SolidExplorer.Next() )
1117                 testFace = TopoDS::Face( SolidExplorer.Current() );
1118             }
1119
1120           BRepAdaptor_Surface FSurf( testFace );
1121           Standard_Boolean SolidIsSphereOrTorus = Standard_False;
1122           
1123           if( FSurf.GetType() == GeomAbs_Sphere ||  FSurf.GetType() == GeomAbs_Torus )
1124             {
1125               Standard_Real minU = FSurf.FirstUParameter();
1126               Standard_Real maxU = FSurf.LastUParameter();
1127               Standard_Real minV = FSurf.FirstVParameter();
1128               Standard_Real maxV = FSurf.LastVParameter();
1129               Standard_Boolean yesU = ( Abs(minU - 0.) < 1.e-9 && Abs(maxU - 2*M_PI) < 1.e-9 );
1130               Standard_Boolean yesV = ( FSurf.GetType() == GeomAbs_Sphere ) ?
1131                 ( Abs(minV - (-M_PI/2.)) < 1.e-9 && Abs(maxV - M_PI/2.) < 1.e-9 ) :
1132                 ( Abs(minV - 0.) < 1.e-9 && Abs(maxV - 2*M_PI) < 1.e-9 );
1133               SolidIsSphereOrTorus = ( yesU && yesV );
1134             }
1135
1136           if( FSurf.GetType() == GeomAbs_SurfaceOfRevolution )
1137             {
1138               Standard_Boolean areBothPeriodic = ( FSurf.IsUPeriodic() && FSurf.IsVPeriodic() );
1139               if( areBothPeriodic )
1140                 {
1141                   Standard_Boolean yesU = ( Abs(FSurf.UPeriod() - M_PI) < 1.e-9 || Abs(FSurf.UPeriod() - 2*M_PI) < 1.e-9 );
1142                   Standard_Boolean yesV = ( Abs(FSurf.VPeriod() - M_PI) < 1.e-9 || Abs(FSurf.VPeriod() - 2*M_PI) < 1.e-9 );
1143                   SolidIsSphereOrTorus = ( yesU && yesV );
1144                 }
1145             }
1146
1147           if( SolidIsSphereOrTorus )
1148               return result;
1149
1150           Standard_Boolean SecondShellOk = Standard_True;
1151           TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1152           aMapEF.Clear();
1153           Standard_Integer NbEdges = 0, NbFaces = 0, iE = 0;
1154
1155           if( NbFacesSol1 == 1 )
1156             TopExp::MapShapesAndAncestors(S2, TopAbs_EDGE, TopAbs_FACE, aMapEF);
1157           else
1158             TopExp::MapShapesAndAncestors(S1, TopAbs_EDGE, TopAbs_FACE, aMapEF);
1159
1160           NbEdges = aMapEF.Extent();
1161           for( iE = 1; iE <= NbEdges; iE++)
1162             {
1163               const TopTools_ListOfShape& listFaces = aMapEF.FindFromIndex( iE );
1164               NbFaces = listFaces.Extent();
1165               if( NbFaces != 2 )
1166                 {
1167                   SecondShellOk = Standard_False;
1168                   break;
1169                 }
1170             }
1171           aMapEF.Clear();
1172
1173           if( SecondShellOk )
1174             result = (NbFacesSol1 == 1) ? 1 : 2;
1175         }
1176       else
1177         {
1178           // ************************** IMPORTANT !!! ************************************
1179           // both shells are of more than 2 faces. if both solids have invalid shells
1180           // we do nothing and just return. on the other hand if only one shell is valid
1181           // currently we should suppose that solid with invalid shell is a half space too,
1182           // but this is not always true.
1183           //
1184           // so this suggestion must be developed carefully. while we don't classify it!
1185           // *****************************************************************************
1186         }
1187 #ifdef OCCT_DEBUG
1188       if( result != 0 )
1189         cout << "# one of the SOLIDs probably is a HALF SPACE" << endl;
1190 #endif
1191     }
1192
1193   return result;
1194 }
1195
1196 //=======================================================================
1197 //function : GetNewSolid
1198 //purpose  : rebuild halfspace solid adding new "face on infinity"
1199 //           to build correct bounding box to classify carefully
1200 //           "rejected shapes".
1201 //=======================================================================
1202 static TopoDS_Solid GetNewSolid(const TopoDS_Shape& S, TopoDS_Face& F)
1203 {
1204   // "new solid" is a new halfspace solid consists of two faces now: the first face is a face
1205   // used to build halfspace solid and the second face is a new "face on infinity" specially
1206   // created to constuct correct bounding box around halfspace solid with bounds more wide than
1207   // previous one.
1208
1209   // the following algorithm is used:
1210   // 1. get face used to build halfspace solid and calculate its normal, Min/Max (U,V) parameters,
1211   //    four points lying on the surface of the face inside its restrictions, surface, tolerance
1212   //    and location.
1213   // 2. define the direction into the halfspace solid and project four points along this direction
1214   //    on infinite distance. then use those points to create "face on infinity".
1215   // 3. build new shell with two new faces and new "halfspace solid".
1216   // 4. return this solid and "face on infinity" to remove it and all its subshapes from the list
1217   //    of rejected shapes.
1218
1219   TopExp_Explorer ShapeExplorer;
1220
1221   TopoDS_Face hsFace;
1222   
1223   for( ShapeExplorer.Init(S, TopAbs_FACE); ShapeExplorer.More(); ShapeExplorer.Next() )
1224     hsFace = TopoDS::Face( ShapeExplorer.Current() );
1225
1226   BRepAdaptor_Surface ASurf( hsFace );
1227   
1228   Standard_Real MinU = ASurf.FirstUParameter();
1229   Standard_Real MaxU = ASurf.LastUParameter();
1230   Standard_Real MinV = ASurf.FirstVParameter();
1231   Standard_Real MaxV = ASurf.LastUParameter();
1232
1233   Standard_Real MidU = (MaxU + MinU) * 0.5;
1234   Standard_Real MidV = (MaxV + MinV) * 0.5;
1235
1236   gp_Pnt MidP;
1237   gp_Vec SurfDU, SurfDV;
1238   ASurf.D1( MidU, MidV, MidP, SurfDU, SurfDV );
1239   
1240   gp_Vec Normal = SurfDU.Crossed( SurfDV );
1241
1242   if( hsFace.Orientation() == TopAbs_FORWARD )
1243     Normal *= -1.e+10;
1244   else
1245     Normal *= 1.e+10;
1246
1247   Standard_Real Pu1 = MinU + Abs( (MaxU - MinU) / 4. );
1248   Standard_Real Pu2 = MinU + Abs( (MaxU - MinU) / 4. * 3. );
1249   Standard_Real Pv1 = MinV + Abs( (MaxV - MinV) / 4. );
1250   Standard_Real Pv2 = MinV + Abs( (MaxV - MinV) / 4. * 3. );
1251
1252   gp_Pnt P1, P2, P3, P4;
1253   ASurf.D0( Pu1, Pv1, P1 );
1254   ASurf.D0( Pu1, Pv2, P2 );
1255   ASurf.D0( Pu2, Pv1, P3 );
1256   ASurf.D0( Pu2, Pv2, P4 ); 
1257
1258   P1.Translate( Normal );
1259   P2.Translate( Normal );
1260   P3.Translate( Normal );
1261   P4.Translate( Normal );
1262
1263   BRepLib_MakeEdge mke1( P1, P2 );
1264   BRepLib_MakeEdge mke2( P2, P4 );
1265   BRepLib_MakeEdge mke3( P4, P3 );
1266   BRepLib_MakeEdge mke4( P3, P1 );
1267
1268   TopoDS_Edge e1 = mke1.Edge();
1269   TopoDS_Edge e2 = mke2.Edge();
1270   TopoDS_Edge e3 = mke3.Edge();
1271   TopoDS_Edge e4 = mke4.Edge();
1272
1273   BRepLib_MakeWire mkw( e1, e2, e3, e4 );
1274   TopoDS_Wire w = mkw.Wire();
1275
1276   BRepLib_MakeFace mkf( w );
1277   TopoDS_Face infFace = mkf.Face();
1278   
1279   TopoDS_Shell newShell;
1280   TopoDS_Solid newSolid;
1281
1282   BRep_Builder newShellBuilder;
1283   newShellBuilder.MakeShell( newShell );
1284   newShellBuilder.Add( newShell, hsFace );
1285   newShellBuilder.Add( newShell, infFace );
1286   newShell.Closed (BRep_Tool::IsClosed (newShell));
1287
1288   BRep_Builder newSolidBuilder;
1289   newSolidBuilder.MakeSolid( newSolid );
1290   newSolidBuilder.Add( newSolid, newShell );
1291
1292   F = infFace;
1293   return newSolid;
1294 }