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