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