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