0030151: Modeling Algorithms - Removal of the API level of old Boolean operations...
[occt.git] / src / BRepAlgo / BRepAlgo_BooleanOperation.cxx
1 // Created on: 1993-10-15
2 // Created by: Remi LEQUETTE
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 #define TRC 0 
18 #define MODIF 1 
19
20
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepAlgo_BooleanOperation.hxx>
24 #include <BRepBuilderAPI_Sewing.hxx>
25 #include <BRepCheck.hxx>
26 #include <BRepCheck_Edge.hxx>
27 #include <BRepCheck_Shell.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib.hxx>
30 #include <BRepTools_Substitution.hxx>
31 #include <TopExp.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopOpeBRep_DSFiller.hxx>
36 #include <TopOpeBRepBuild_HBuilder.hxx>
37 #include <TopOpeBRepBuild_Tools.hxx>
38 #include <TopOpeBRepDS_BuildTool.hxx>
39 #include <TopOpeBRepDS_HDataStructure.hxx>
40 #include <TopOpeBRepTool_GeomTool.hxx>
41 #include <TopOpeBRepTool_OutCurveType.hxx>
42 #include <TopTools_IndexedMapOfShape.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <TopTools_ListOfShape.hxx>
45 #include <TopTools_MapOfShape.hxx>
46
47 //  sewing
48 #ifdef OCCT_DEBUG
49 extern Standard_Boolean TopOpeBRepTool_GetcontextNOSEW();
50 #endif
51
52 #define Opecom(st1,st2) (((st1)==TopAbs_IN) && ((st2)==TopAbs_IN))
53 #define Opefus(st1,st2) (((st1)==TopAbs_OUT) && ((st2)==TopAbs_OUT))
54 #define Opecut(st1,st2) (((st1)==TopAbs_OUT) && ((st2)==TopAbs_IN))
55
56 // -------------------------------------------------------------------
57 static void Sub_Classify(TopExp_Explorer& Ex,
58                          const TopAbs_State St1,
59                          TopTools_ListOfShape& Solids2,
60                          BRep_Builder& BB,
61                          TopTools_ListIteratorOfListOfShape& LIter,
62                          TopoDS_Shape& myShape); 
63
64
65 #ifdef OCCT_DEBUG
66 Standard_IMPORT Standard_Integer TopOpeBRepTool_BOOOPE_CHECK_DEB;
67 #endif
68
69 //modified by NIZHNY-MZV  Wed Apr 19 17:19:11 2000
70 //see comments at the top of file TopOpeBRepBuild_Builder1.cxx
71 //about using of this global variable
72 extern Standard_Boolean GLOBAL_USE_NEW_BUILDER;
73 //
74 //modified by NIZNHY-PKV Sun Dec 15 17:17:56 2002 f
75 extern void FDSCNX_Close();// see TopOpeBRepDS_connex.cxx
76 extern void FDSSDM_Close();// see TopOpeBRepDS_samdom.cxx
77
78 //=======================================================================
79 //function : ~BRepAlgo_BooleanOperation
80 //purpose  : 
81 //=======================================================================
82 BRepAlgo_BooleanOperation::~BRepAlgo_BooleanOperation()
83 {
84   FDSSDM_Close();
85   FDSCNX_Close();
86 }
87 //modified by NIZNHY-PKV Sun Dec 15 17:17:58 2002 t
88
89 //=======================================================================
90 //function : BRepAlgoAPI_BooleanOperation
91 //purpose  : 
92 //=======================================================================
93   BRepAlgo_BooleanOperation::BRepAlgo_BooleanOperation(const TopoDS_Shape& S1, 
94                                                        const TopoDS_Shape& S2)
95 : myS1(S1),myS2(S2),myBuilderCanWork(Standard_False)
96 {
97   TopOpeBRepDS_BuildTool BT;
98   myHBuilder = new TopOpeBRepBuild_HBuilder(BT);
99 }
100
101 //=======================================================================
102 //function : PerformDS
103 //purpose  : 
104 //=======================================================================
105   void BRepAlgo_BooleanOperation::PerformDS()
106 {
107 //  const Standard_Boolean CheckShapes = Standard_True;
108
109   // create a data structure
110   Handle(TopOpeBRepDS_HDataStructure) HDS;
111   if (myHBuilder->DataStructure().IsNull())
112     HDS = new TopOpeBRepDS_HDataStructure();
113   else {
114     HDS = myHBuilder->DataStructure();
115     HDS->ChangeDS().Init();
116   }
117
118   // fill the data Structure
119   TopOpeBRep_DSFiller DSFiller;
120  
121   // define face/face intersection tolerances
122   Standard_Boolean forcetoli = Standard_False;
123   if (forcetoli) {
124     Standard_Real tolarc=0,toltang=0;
125     TopOpeBRep_ShapeIntersector& tobsi = DSFiller.ChangeShapeIntersector();
126     TopOpeBRep_FacesIntersector& tobfi = tobsi.ChangeFacesIntersector();
127     tobfi.ForceTolerances(tolarc,toltang);
128   }
129   DSFiller.Insert(myS1,myS2,HDS);
130
131   // 020499 : JYL : reject if there is an edge of the SD
132   // not coded sameparameter and not degenerated
133   Standard_Boolean esp = HDS->EdgesSameParameter();
134   Standard_Boolean tede = Standard_True;
135   if (!esp) {
136     Standard_Integer i,n = HDS->NbShapes();
137     for (i = 1 ; i <= n; i++) {
138       const TopoDS_Shape& s = HDS->Shape(i);
139       if ( s.ShapeType() == TopAbs_EDGE ) {
140         const TopoDS_Edge& e = TopoDS::Edge(s);
141         Standard_Boolean sp = BRep_Tool::SameParameter(e);
142         Standard_Boolean de = BRep_Tool::Degenerated(e);
143         if ( !sp && !de ) {
144           tede = Standard_False;
145           break;
146         }
147       }
148     }
149   }
150   myBuilderCanWork = (esp || tede) ;
151 #ifdef OCCT_DEBUG
152   if (!esp) std::cout<<"BRepAlgo_BooleanOperation(DEB) some edges not SameParameter"<<std::endl;
153 #endif  
154   if (!myBuilderCanWork) return;
155   
156   Standard_Real tol3dAPPROX = 1e-7;
157   Standard_Real tol2dAPPROX = 1e-7;
158   // set tolerance values used by the APPROX process
159   
160   TopOpeBRepDS_BuildTool& BTofBuilder = myHBuilder->ChangeBuildTool();
161   TopOpeBRepTool_GeomTool& GTofBTofBuilder = BTofBuilder.ChangeGeomTool();
162   GTofBTofBuilder.SetTolerances(tol3dAPPROX,tol2dAPPROX);
163   
164   //modified by NIZHNY-MZV  Thu Apr 20 09:35:44 2000
165   //see comments at the top of file TopOpeBRepBuild_Builder1.cxx
166   //about using of this global variable
167   GLOBAL_USE_NEW_BUILDER = Standard_True;
168   myHBuilder->Perform(HDS,myS1,myS2);
169   GLOBAL_USE_NEW_BUILDER = Standard_False;
170 }
171
172 //=======================================================================
173 //function : Perform
174 //purpose  : 
175 //=======================================================================
176   void  BRepAlgo_BooleanOperation::Perform(const TopAbs_State St1, 
177                                            const TopAbs_State St2)
178 {
179   if ( ! BuilderCanWork() ) {
180     return;
181   }
182
183   // modif JYL suite aux modifs LBR #if MODIF ...
184   // on privilegie le traitement KPart (si c'en est un) 
185   // a tous les autres
186   Standard_Integer kp = myHBuilder->IsKPart();
187   BRep_Builder BB;
188   Standard_Boolean sewing = Standard_True;
189   if ( kp ) {
190     //modified by NIZHNY-MZV  Thu Apr 20 09:34:33 2000
191     //see comments at the top of file TopOpeBRepBuild_Builder1.cxx
192     //about using of this global variable
193     GLOBAL_USE_NEW_BUILDER = Standard_True;
194     myHBuilder->MergeKPart(St1,St2);
195     GLOBAL_USE_NEW_BUILDER = Standard_False;
196
197     BB.MakeCompound(TopoDS::Compound(myShape));
198     Done();
199
200     TopTools_ListIteratorOfListOfShape its(myHBuilder->Merged(myS1,St1));
201     for(; its.More(); its.Next()) BB.Add(myShape,its.Value());
202
203   }
204   else {
205 #if MODIF 
206
207     //======================================================================
208     //== Exploration of input shapes 
209     //== Creation of the list of solids 
210     //== Creation of the list of faces OUT OF solid
211     //== Creation of the list of edges OUT OF face
212     Standard_Integer nbs1,nbs2,nbf1,nbf2,nbe1,nbe2,nbv1,nbv2;
213
214     TopTools_ListOfShape Solids1,Solids2,Faces1,Faces2,Edges1,Edges2,Vertex1,Vertex2;
215     TopExp_Explorer Ex;
216     for(Ex.Init(myS1,TopAbs_SOLID),nbs1=0; Ex.More(); Ex.Next()) {
217       Solids1.Append(Ex.Current()); nbs1++;
218     }
219     for(Ex.Init(myS2,TopAbs_SOLID),nbs2=0; Ex.More(); Ex.Next()) { 
220       Solids2.Append(Ex.Current()); nbs2++;
221     }
222     //== Faces not  in a solid
223     for(Ex.Init(myS1,TopAbs_FACE,TopAbs_SOLID),nbf1=0; Ex.More(); Ex.Next())  { 
224       Faces1.Append(Ex.Current()); nbf1++;
225     }
226     for(Ex.Init(myS2,TopAbs_FACE,TopAbs_SOLID),nbf2=0; Ex.More(); Ex.Next())  {
227       Faces2.Append(Ex.Current()); nbf2++;
228     }
229     //== Edges not in a solid
230     for(Ex.Init(myS1,TopAbs_EDGE,TopAbs_FACE),nbe1=0;  Ex.More(); Ex.Next())  { 
231       Edges1.Append(Ex.Current()); nbe1++;
232     }
233     for(Ex.Init(myS2,TopAbs_EDGE,TopAbs_FACE),nbe2=0;  Ex.More(); Ex.Next()) {
234       Edges2.Append(Ex.Current()); nbe2++;
235     }
236     //== Vertices not in an edge
237     for(Ex.Init(myS1,TopAbs_VERTEX,TopAbs_EDGE),nbv1=0;  Ex.More(); Ex.Next())  { 
238       Vertex1.Append(Ex.Current()); nbv1++;
239     }
240     for(Ex.Init(myS2,TopAbs_VERTEX,TopAbs_EDGE),nbv2=0;  Ex.More(); Ex.Next()) {
241       Vertex2.Append(Ex.Current()); nbv2++;
242     }
243
244     //-- std::cout<<"Solids1: "<<nbs1<<"  Faces1: "<<nbf1<<" Edges1:"<<nbe1<<" Vtx1:"<<nbv1<<std::endl;
245     //-- std::cout<<"Solids2: "<<nbs2<<"  Faces2: "<<nbf2<<" Edges2:"<<nbe2<<" Vtx2:"<<nbv2<<std::endl;
246
247     //== 
248
249     //== Reject operations without direction 
250   
251
252     //-- Cut Solid by Edge 
253 //    Standard_Boolean Correct = Standard_True;
254     if(    (nbs1 && nbs2==0 && St1==TopAbs_OUT && St2==TopAbs_IN) 
255        ||  (nbs2 && nbs1==0 && St2==TopAbs_OUT && St1==TopAbs_IN)) { 
256       //-- std::cout<<"*****  Invalid Operation : Cut of a Solid by a Non Solid "<<std::endl;
257       Done();
258       return;
259     }
260
261     if(    (nbs1 && nbs2==0 && St1==TopAbs_OUT && St2==TopAbs_OUT) 
262        ||  (nbs2 && nbs1==0 && St2==TopAbs_OUT && St1==TopAbs_OUT)) { 
263       //-- std::cout<<"*****  Invalid Operation : Fusion of a Solid and a Non Solid "<<std::endl;
264       Done();
265       return;
266     }
267  
268
269     if(    (nbs1>0 && nbs2>0) 
270        &&  (nbe1 || nbe2 || nbf1 || nbf2 || nbv1 || nbv2)) { 
271       //-- std::cout<<"***** Not Yet Implemented : Compound of solid and non Solid"<<std::endl;
272       Done();
273       return;
274     }
275     //======================================================================
276     // make a compound with the new solids
277     BB.MakeCompound(TopoDS::Compound(myShape));
278     
279     TopTools_ListIteratorOfListOfShape LIter;
280     //----------------------------------------------------------------------
281     TopoDS_Shape SNULL;
282     
283     if (nbf1 && nbf2) {
284       SNULL.Nullify();
285       if ( Opecom(St1,St2) ) {
286         TopTools_ListIteratorOfListOfShape itloe = myHBuilder->Section();
287         for(; itloe.More(); itloe.Next()) BB.Add(myShape,itloe.Value());
288       } 
289       else {
290         if(nbf1) { 
291           myHBuilder->MergeShapes(myS1,St1,SNULL,St2);
292
293           for(LIter.Initialize(Faces1);LIter.More();LIter.Next()) {
294             if (myHBuilder->IsSplit(LIter.Value(),St1)) {
295               TopTools_ListIteratorOfListOfShape its;
296               for(its.Initialize(myHBuilder->Splits(LIter.Value(),St1));
297                   its.More();its.Next()) BB.Add(myShape,its.Value());
298             }
299             else {
300               const TopoDS_Shape& LV = LIter.Value();
301               if(  (LV.Orientation() == TopAbs_EXTERNAL && St1==TopAbs_OUT )        
302                  ||(LV.Orientation() == TopAbs_INTERNAL && St1==TopAbs_IN  )) {
303                 BB.Add(myShape,LV);
304               }
305               else { 
306                 //-- Classify : 
307                 Sub_Classify(Ex,St1,Solids2,BB,LIter,myShape); 
308               }
309               //-- End Classification 
310             }
311           }
312         } // nbf1
313         SNULL.Nullify();    
314         if ( Opefus(St1,St2) ) {
315           if(nbf2) {
316             myHBuilder->MergeShapes(SNULL,St1,myS2,St2);
317             for(LIter.Initialize(Faces2);LIter.More();LIter.Next()) {
318               if (myHBuilder->IsSplit(LIter.Value(),St2)) {
319                 TopTools_ListIteratorOfListOfShape its;
320                 for(its.Initialize(myHBuilder->Splits(LIter.Value(),St2));
321                     its.More();its.Next()) BB.Add(myShape,its.Value());
322               }
323               else {
324                 const TopoDS_Shape& LV = LIter.Value();
325                 if(  (LV.Orientation() == TopAbs_EXTERNAL && St2==TopAbs_OUT )      
326                    ||(LV.Orientation() == TopAbs_INTERNAL && St2==TopAbs_IN  )) {
327                   BB.Add(myShape,LV);
328                 }
329                 else { 
330                   //-- Classify : 
331                   Sub_Classify(Ex,St2,Solids1,BB,LIter,myShape); 
332                 }
333                 //-- End Classification         
334               }
335             }
336           } // nbf2
337         } // Fus
338       }
339     } // nbf1 && nbf2
340     else if (nbf1 || nbf2) {
341       SNULL.Nullify();
342       if(nbf1) { 
343         myHBuilder->MergeShapes(myS1,St1,SNULL,St2);
344         // modified by IFV for treating operation between shell and solid
345         const TopTools_ListOfShape& MergedShapes = myHBuilder->Merged(myS1,St1);
346         TopTools_IndexedMapOfShape aMapOfFaces;
347
348         sewing = Standard_False;
349
350         if(MergedShapes.Extent() != 0) {
351           TopTools_ListIteratorOfListOfShape its(MergedShapes);
352           for(; its.More(); its.Next()) {
353             BB.Add(myShape,its.Value());
354           }
355           TopExp::MapShapes(myShape, TopAbs_FACE, aMapOfFaces);
356         }
357
358         for(LIter.Initialize(Faces1);LIter.More();LIter.Next()) {
359
360           if (myHBuilder->IsSplit(LIter.Value(),St1)) {
361             TopTools_ListIteratorOfListOfShape its;
362             for(its.Initialize(myHBuilder->Splits(LIter.Value(),St1));
363                 its.More();its.Next()) {
364               if(!aMapOfFaces.Contains(its.Value())) BB.Add(myShape,its.Value());
365             }
366           }
367           else {
368             const TopoDS_Shape& LV = LIter.Value();
369             if(!aMapOfFaces.Contains(LV)) {
370               if(  (LV.Orientation() == TopAbs_EXTERNAL && St1==TopAbs_OUT )        
371                  ||(LV.Orientation() == TopAbs_INTERNAL && St1==TopAbs_IN  )) {
372                 BB.Add(myShape,LV);
373               }
374               else { 
375                 //-- Classify : 
376                 Sub_Classify(Ex,St1,Solids2,BB,LIter,myShape); 
377               }
378               //-- End Classification 
379             }
380           }
381         }
382       } // nbf1
383       SNULL.Nullify();    
384       if(nbf2) {
385         myHBuilder->MergeShapes(SNULL,St1,myS2,St2);
386         // modified by IFV for treating operation between shell and solid
387         const TopTools_ListOfShape& MergedShapes = myHBuilder->Merged(myS2,St2);
388         TopTools_IndexedMapOfShape aMapOfFaces;
389         sewing = Standard_False;
390
391         if(MergedShapes.Extent() != 0) {
392           TopTools_ListIteratorOfListOfShape its(MergedShapes);
393           for(; its.More(); its.Next()) {
394             BB.Add(myShape,its.Value());
395           }
396           TopExp::MapShapes(myShape, TopAbs_FACE, aMapOfFaces);
397         }
398
399         for(LIter.Initialize(Faces2);LIter.More();LIter.Next()) {
400           if (myHBuilder->IsSplit(LIter.Value(),St2)) {
401             TopTools_ListIteratorOfListOfShape its;
402             for(its.Initialize(myHBuilder->Splits(LIter.Value(),St2));
403                 its.More();its.Next()) {
404               if(!aMapOfFaces.Contains(its.Value())) BB.Add(myShape,its.Value());
405             }
406           }
407           else {
408             const TopoDS_Shape& LV = LIter.Value();
409             if(!aMapOfFaces.Contains(LV)) {
410               if(  (LV.Orientation() == TopAbs_EXTERNAL && St2==TopAbs_OUT )        
411                  ||(LV.Orientation() == TopAbs_INTERNAL && St2==TopAbs_IN  )) {
412                 BB.Add(myShape,LV);
413               }
414               else { 
415                 //-- Classify : 
416                 Sub_Classify(Ex,St2,Solids1,BB,LIter,myShape); 
417               }
418               //-- End Classification   
419             }
420           }
421         }
422       } // nbf2
423     } // (nbf1 || nbf2)
424     
425     //----------------------------------------------------------------------
426     if(nbe1) { 
427       myHBuilder->MergeShapes(myS1,St1,SNULL,St2);
428
429       for(LIter.Initialize(Edges1);LIter.More();LIter.Next()) {
430         if (myHBuilder->IsSplit(LIter.Value(),St1)) {
431           TopTools_ListIteratorOfListOfShape its;
432           for(its.Initialize(myHBuilder->Splits(LIter.Value(),St1));
433               its.More();its.Next()) {
434             BB.Add(myShape,its.Value());
435           }
436         }
437         else {
438           const TopoDS_Shape& LV = LIter.Value();
439           if(  (LV.Orientation() == TopAbs_EXTERNAL && St1==TopAbs_OUT )            
440              ||(LV.Orientation() == TopAbs_INTERNAL && St1==TopAbs_IN  )) {
441             BB.Add(myShape,LV);
442           }
443           else { 
444             //-- Classify : 
445             Sub_Classify(Ex,St1,Solids2,BB,LIter,myShape); 
446           }
447           //-- End Classification 
448         }
449       }
450     }
451     if(nbe2) { 
452       myHBuilder->MergeShapes(SNULL,St1,myS2,St2);
453       
454       for(LIter.Initialize(Edges2);LIter.More();LIter.Next()) {
455         if (myHBuilder->IsSplit(LIter.Value(),St2)) {
456           TopTools_ListIteratorOfListOfShape its;
457           for(its.Initialize(myHBuilder->Splits(LIter.Value(),St2));
458               its.More();its.Next()) {
459             BB.Add(myShape,its.Value());
460           }
461         }
462         else {
463           const TopoDS_Shape& LV = LIter.Value();
464           if(  (LV.Orientation() == TopAbs_EXTERNAL && St2==TopAbs_OUT )            
465              ||(LV.Orientation() == TopAbs_INTERNAL && St2==TopAbs_IN  ))  {     
466             BB.Add(myShape,LV);
467           }
468           else { 
469             //-- Classify : 
470             Sub_Classify(Ex,St2,Solids1,BB,LIter,myShape); 
471           }
472           //-- End Classification 
473         }
474       }
475     }
476     //----------------------------------------------------------------------
477     //-- V1:Vertex1   state1 = OUT   -> Preserve V1 if V1 is Out all S2
478     //-- V1:Vertex1   state1 = IN    -> Preserve V1 if V1 is In one of S2 
479     if(nbv1 && nbs2) { 
480       if(St1 == TopAbs_IN) { 
481         for(LIter.Initialize(Vertex1);LIter.More();LIter.Next()) {
482           Standard_Boolean keep = Standard_False;
483           Standard_Boolean ok = Standard_True;
484           const TopoDS_Vertex& V=TopoDS::Vertex(LIter.Value());
485           gp_Pnt P=BRep_Tool::Pnt(V);
486           Standard_Real Tol = BRep_Tool::Tolerance(V);
487           TopTools_ListIteratorOfListOfShape SIter;
488           for(SIter.Initialize(Solids2);
489               SIter.More() && ok==Standard_True;
490               SIter.Next()) {     
491             BRepClass3d_SolidClassifier SolClass(SIter.Value());
492             SolClass.Perform(P,Tol);
493             if(SolClass.State() == TopAbs_IN) {
494               ok=Standard_False;
495               keep = Standard_True;
496             }
497           }
498           if(keep) { 
499             BB.Add(myShape,LIter.Value());
500           }
501         }
502       }
503       else { 
504         if(St1 == TopAbs_OUT) { 
505           for(LIter.Initialize(Vertex1);LIter.More();LIter.Next()) {
506             Standard_Boolean keep = Standard_True;
507             Standard_Boolean ok = Standard_True;
508             const TopoDS_Vertex& V=TopoDS::Vertex(LIter.Value());
509             gp_Pnt P=BRep_Tool::Pnt(V);
510             Standard_Real Tol = BRep_Tool::Tolerance(V);
511             TopTools_ListIteratorOfListOfShape SIter;
512             for(SIter.Initialize(Solids2);
513                 SIter.More() && ok==Standard_True;
514                 SIter.Next()) {           
515               BRepClass3d_SolidClassifier SolClass(SIter.Value());
516               SolClass.Perform(P,Tol);
517               if(SolClass.State() != TopAbs_OUT) {
518                 keep = Standard_False;
519                 ok   = Standard_False;
520               }
521             }
522             if(keep) { 
523               BB.Add(myShape,LIter.Value());
524             }
525           }
526         }
527       }    
528     }
529   
530     if(nbv2 && nbs1) { 
531       if(St2 == TopAbs_IN) { 
532         for(LIter.Initialize(Vertex2);LIter.More();LIter.Next()) {
533           Standard_Boolean keep = Standard_False;
534           Standard_Boolean ok = Standard_True;
535           const TopoDS_Vertex& V=TopoDS::Vertex(LIter.Value());
536           gp_Pnt P=BRep_Tool::Pnt(V);
537           Standard_Real Tol = BRep_Tool::Tolerance(V);
538           TopTools_ListIteratorOfListOfShape SIter;
539           for(SIter.Initialize(Solids1);
540               SIter.More() && ok==Standard_True;
541               SIter.Next()) {     
542             BRepClass3d_SolidClassifier SolClass(SIter.Value());
543             SolClass.Perform(P,Tol);
544             if(SolClass.State() == TopAbs_IN) {
545               ok=Standard_False;
546               keep = Standard_True;
547             }
548           }
549           if(keep) { 
550             BB.Add(myShape,LIter.Value());
551           }
552         }
553       }
554       else { 
555         if(St2 == TopAbs_OUT) { 
556           for(LIter.Initialize(Vertex2);LIter.More();LIter.Next()) {
557             Standard_Boolean keep = Standard_True;
558             Standard_Boolean ok = Standard_True;
559             const TopoDS_Vertex& V=TopoDS::Vertex(LIter.Value());
560             gp_Pnt P=BRep_Tool::Pnt(V);
561             Standard_Real Tol = BRep_Tool::Tolerance(V);
562             TopTools_ListIteratorOfListOfShape SIter;
563             for(SIter.Initialize(Solids1);
564                 SIter.More() && ok==Standard_True;
565                 SIter.Next()) {           
566               BRepClass3d_SolidClassifier SolClass(SIter.Value());
567               SolClass.Perform(P,Tol);
568               if(SolClass.State() != TopAbs_OUT) {
569                 keep = Standard_False;
570                 ok   = Standard_False;
571               }
572             }
573             if(keep) { 
574               BB.Add(myShape,LIter.Value());
575             }
576           }
577         }
578       }    
579     }
580     
581     if(nbs1 && nbs2 ) { 
582       myHBuilder->MergeShapes(myS1,St1,myS2,St2);
583       if(myHBuilder->IsMerged(myS1,St1)) { 
584         TopTools_ListIteratorOfListOfShape its;
585         its = myHBuilder->Merged(myS1,St1);
586         Standard_Integer nbSolids = 0;
587         for(; its.More(); its.Next(), nbSolids++) { 
588           BB.Add(myShape,its.Value());
589         }
590       }
591     }
592   
593 #else 
594
595     myHBuilder->MergeSolids(myS1,St1,myS2,St2);
596     TopTools_ListIteratorOfListOfShape its;
597   
598     BB.MakeCompound(TopoDS::Compound(myShape));
599     its = myHBuilder->Merged(myS1,St1);
600     while (its.More()) {
601       BB.Add(myShape,its.Value());
602       its.Next();
603     }
604
605 #endif
606 // #if MODIF
607
608   }
609
610   // Creation of the Map used in IsDeleted.
611   TopExp_Explorer ex;
612   ex.Init(myShape,TopAbs_FACE);
613   for (; ex.More(); ex.Next()) myMap.Add(ex.Current());
614   ex.Init(myShape,TopAbs_EDGE); // for FRIKO
615   for (; ex.More(); ex.Next()) myMap.Add(ex.Current());
616   
617   // Checking same parameter of new edges of section
618   Standard_Real eTol,cTol;
619   for (myHBuilder->InitSection(1); 
620        myHBuilder->MoreSection(); 
621        myHBuilder->NextSection()) {
622     const TopoDS_Shape& cur = myHBuilder->CurrentSection();
623     if (cur.ShapeType()==TopAbs_EDGE) {
624       BRepCheck_Edge bce(TopoDS::Edge(cur));
625       cTol=bce.Tolerance();
626       eTol = BRep_Tool::Tolerance(TopoDS::Edge(cur));
627       if (eTol<cTol) {
628         BB.UpdateEdge(TopoDS::Edge(cur), cTol);
629         for (ex.Init(cur, TopAbs_VERTEX); ex.More(); ex.Next()) {
630           eTol = BRep_Tool::Tolerance(TopoDS::Vertex(ex.Current()));
631           if (eTol<cTol) {
632             // Update can only increase tolerance, so if the vertex 
633             // has a greater tolerance thanits edges it is not touched
634             BB.UpdateVertex(TopoDS::Vertex(ex.Current()), cTol);
635           }
636         }
637       }
638     }
639   }
640
641   Standard_Real maxTol = RealLast();    // MSV: unlimit tolerance
642   TopOpeBRepBuild_Tools::CorrectTolerances(myShape,maxTol);
643
644   TopExp_Explorer ex1, ex2, ex3;
645   TopTools_ListOfShape theOldShell, theNewShell;
646   Standard_Boolean modif =Standard_False;
647
648 #ifdef OCCT_DEBUG
649   Standard_Boolean nosew = TopOpeBRepTool_GetcontextNOSEW();
650   if (nosew) sewing = Standard_False;
651 #endif
652
653   if (sewing) {
654     topToSew.Clear();
655     for (ex1.Init(myShape, TopAbs_SHELL); ex1.More(); ex1.Next()) {
656       BRepCheck_Shell bcs(TopoDS::Shell(ex1.Current()));
657       if (bcs.Closed()==BRepCheck_NotClosed) {
658         // it is required to add them face by face to avoid IsModified on faces
659         BRepBuilderAPI_Sewing brts;
660         for (ex3.Init(ex1.Current(), TopAbs_FACE); ex3.More(); ex3.Next()) {
661           brts.Add(ex3.Current());
662         }
663         brts.Perform();
664         ex2.Init(brts.SewedShape(), TopAbs_SHELL);
665         if (ex2.More()) {
666           ex2.Next();
667           if (!ex2.More()) {
668             ex2.Init(brts.SewedShape(), TopAbs_SHELL);
669             theOldShell.Append(ex1.Current());
670             theNewShell.Append(ex2.Current());
671             modif =Standard_True;
672             for (ex3.Init(ex1.Current(), TopAbs_EDGE); ex3.More(); ex3.Next()) {
673               const TopoDS_Edge& ledg = TopoDS::Edge(ex3.Current());
674               if (brts.IsSectionBound(ledg)) {
675                 topToSew.Bind(ledg, brts.SectionToBoundary(ledg));
676                 if (!BRep_Tool::SameParameter(brts.SectionToBoundary(ledg))) {
677                   BRepLib::SameParameter(ledg, BRep_Tool::Tolerance(brts.SectionToBoundary(ledg)));
678                 }
679               }
680             }
681             for (ex3.Init(ex1.Current(), TopAbs_FACE); ex3.More(); ex3.Next()) {
682               if (brts.IsModified(ex3.Current())) {
683                 topToSew.Bind(ex3.Current(), brts.Modified(ex3.Current()));
684               }
685             }
686           }
687         }
688       }
689     }
690   } // sewing
691
692   if (modif) {
693     BRepTools_Substitution bsub;
694     TopTools_ListIteratorOfListOfShape itl(theOldShell);
695     TopTools_ListOfShape forSub;
696     for (; itl.More();itl.Next()) {
697       forSub.Append(theNewShell.First());
698       bsub.Substitute(itl.Value(), forSub);
699       theNewShell.RemoveFirst();
700       forSub.Clear();
701     }
702     bsub.Build(myShape);
703     if (bsub.IsCopied(myShape)) {
704       myShape=(bsub.Copy(myShape)).First();
705     }
706   }
707   
708   Done();
709 }
710
711
712
713 //=======================================================================
714 //function : Builder
715 //purpose  : 
716 //=======================================================================
717   Handle(TopOpeBRepBuild_HBuilder) BRepAlgo_BooleanOperation::Builder()const 
718 {
719   return myHBuilder;
720 }
721
722
723 //=======================================================================
724 //function : TopoDS_Shape&
725 //purpose  : 
726 //=======================================================================
727   const TopoDS_Shape& BRepAlgo_BooleanOperation::Shape1() const 
728 {
729   return myS1;
730 }
731
732
733 //=======================================================================
734 //function : TopoDS_Shape&
735 //purpose  : 
736 //=======================================================================
737   const TopoDS_Shape& BRepAlgo_BooleanOperation::Shape2() const 
738 {
739   return myS2;
740 }
741
742 //=======================================================================
743 //function : BuilderCanWork
744 //purpose  : 
745 //=======================================================================
746   void BRepAlgo_BooleanOperation::BuilderCanWork(const Standard_Boolean Val)
747 {
748   myBuilderCanWork = Val;
749 }
750
751 //=======================================================================
752 //function : BuilderCanWork
753 //purpose  : 
754 //=======================================================================
755   Standard_Boolean BRepAlgo_BooleanOperation::BuilderCanWork() const
756 {
757   return myBuilderCanWork;
758 }
759
760
761 void Sub_Classify(TopExp_Explorer& Ex,
762                   const TopAbs_State St1,
763                   TopTools_ListOfShape& Solids2,
764                   BRep_Builder& BB,
765                   TopTools_ListIteratorOfListOfShape& LIter,
766                   TopoDS_Shape& myShape) { 
767   Ex.Init(LIter.Value(),TopAbs_VERTEX);
768   if(Ex.More()) { 
769     if(St1 == TopAbs_IN) { 
770       Standard_Boolean keep = Standard_False;
771       Standard_Boolean ok = Standard_True;
772       const TopoDS_Vertex& V=TopoDS::Vertex(Ex.Current());
773       gp_Pnt P=BRep_Tool::Pnt(V);
774       Standard_Real Tol = BRep_Tool::Tolerance(V);
775       TopTools_ListIteratorOfListOfShape SIter;
776       for(SIter.Initialize(Solids2);
777           SIter.More() && ok==Standard_True;
778           SIter.Next()) {         
779         BRepClass3d_SolidClassifier SolClass(SIter.Value());
780         SolClass.Perform(P,Tol);
781         if(SolClass.State() == TopAbs_IN) {
782           ok=Standard_False;
783           keep = Standard_True;
784         }
785       }
786       if(keep) { 
787         BB.Add(myShape,LIter.Value());
788       }
789     }
790     else { 
791       if(St1 == TopAbs_OUT) { 
792         Standard_Boolean keep = Standard_True;
793         Standard_Boolean ok = Standard_True;
794         const TopoDS_Vertex& V=TopoDS::Vertex(Ex.Current());
795         gp_Pnt P=BRep_Tool::Pnt(V);
796         Standard_Real Tol = BRep_Tool::Tolerance(V);
797         TopTools_ListIteratorOfListOfShape SIter;
798         for(SIter.Initialize(Solids2);
799             SIter.More() && ok==Standard_True;
800             SIter.Next()) {       
801           BRepClass3d_SolidClassifier SolClass(SIter.Value());
802           SolClass.Perform(P,Tol);
803           if(SolClass.State() != TopAbs_OUT) {
804             keep = Standard_False;
805             ok   = Standard_False;
806           }
807         }
808         if(keep) { 
809           BB.Add(myShape,LIter.Value());
810         }
811       }
812     }
813   }
814 }
815
816
817 //=======================================================================
818 //function : InitParameters
819 //purpose  : Info on geometry : PCurve, Approx, ...
820 //=======================================================================
821 void BRepAlgo_BooleanOperation::InitParameters()
822 {
823   TopOpeBRepDS_BuildTool& BTofBuilder = myHBuilder->ChangeBuildTool();
824   TopOpeBRepTool_GeomTool& GTofBTofBuilder = BTofBuilder.ChangeGeomTool();
825
826   GTofBTofBuilder.Define(TopOpeBRepTool_APPROX);
827   GTofBTofBuilder.DefineCurves(Standard_True);
828   GTofBTofBuilder.DefinePCurves1(Standard_True);
829   GTofBTofBuilder.DefinePCurves2(Standard_True);
830 }
831
832 //=======================================================================
833 //function : Modified
834 //purpose  : 
835 //=======================================================================
836 const TopTools_ListOfShape& BRepAlgo_BooleanOperation::Modified(const TopoDS_Shape& S) 
837 {
838   myGenerated.Clear();
839   TopTools_MapOfShape aMap; // to check if shape can be added in list more then one time
840   aMap.Clear();
841   if (myHBuilder->IsSplit(S, TopAbs_OUT)) {
842     TopTools_ListIteratorOfListOfShape It(myHBuilder->Splits(S, TopAbs_OUT));
843     for(;It.More();It.Next()) {
844       if (topToSew.IsBound(It.Value())) 
845         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
846       else
847         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
848     }
849   }
850   if (myHBuilder->IsSplit(S, TopAbs_IN)) {
851     TopTools_ListIteratorOfListOfShape It(myHBuilder->Splits(S, TopAbs_IN));
852     for(;It.More();It.Next()) {
853       if (topToSew.IsBound(It.Value())) 
854         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
855       else
856         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
857     }
858   }
859   if (myHBuilder->IsSplit(S, TopAbs_ON)) {
860     TopTools_ListIteratorOfListOfShape It(myHBuilder->Splits(S, TopAbs_ON));
861     for(;It.More();It.Next()) {
862       if (topToSew.IsBound(It.Value())) 
863         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
864       else
865         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
866     }
867   }
868
869   if (myHBuilder->IsMerged(S, TopAbs_OUT)) {
870     TopTools_ListIteratorOfListOfShape It(myHBuilder->Merged(S, TopAbs_OUT));
871     for(;It.More();It.Next()) {
872       if (topToSew.IsBound(It.Value())) 
873         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
874       else
875         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
876     }
877   }
878   if (myHBuilder->IsMerged(S, TopAbs_IN)) {
879     TopTools_ListIteratorOfListOfShape It(myHBuilder->Merged(S, TopAbs_IN));
880     for(;It.More();It.Next()) {
881       if (topToSew.IsBound(It.Value())) 
882         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
883       else
884         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
885     }
886   }
887   if (myHBuilder->IsMerged(S, TopAbs_ON)) {
888     TopTools_ListIteratorOfListOfShape It(myHBuilder->Merged(S, TopAbs_ON));
889     for(;It.More();It.Next()) {
890       if (topToSew.IsBound(It.Value())) 
891         {if(aMap.Add(topToSew.Find(It.Value()))) myGenerated.Append(topToSew.Find(It.Value()));}
892       else
893         {if(aMap.Add(It.Value())) myGenerated.Append(It.Value());}
894     }
895   }
896   return myGenerated;
897 }
898
899
900 //=======================================================================
901 //function : IsDeleted
902 //purpose  : 
903 //=======================================================================
904 Standard_Boolean BRepAlgo_BooleanOperation::IsDeleted(const TopoDS_Shape& S) 
905 {
906   Standard_Boolean Deleted = Standard_True; 
907   if (myMap.Contains(S) || 
908       myHBuilder->IsMerged(S, TopAbs_OUT) ||
909       myHBuilder->IsMerged(S, TopAbs_IN)  ||
910       myHBuilder->IsMerged(S, TopAbs_ON)  ||
911       myHBuilder->IsSplit (S, TopAbs_OUT)  ||
912       myHBuilder->IsSplit (S, TopAbs_IN)   ||
913       myHBuilder->IsSplit (S, TopAbs_ON))
914     return Standard_False;
915
916   return Deleted;    
917 }