Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepAlgoAPI / BRepAlgoAPI_BooleanOperation.cxx
1 // File:        BRepAlgoAPI_BooleanOperation.cxx
2 // Created:     Fri Oct 15 11:35:03 1993
3 // Author:      Remi LEQUETTE
4 //              <rle@phylox>
5
6 #include <BRepAlgoAPI_BooleanOperation.ixx>
7
8 #include <BOP_Builder.hxx>
9 #include <BOP_Section.hxx>
10 #include <BOP_ShellShell.hxx>
11 #include <BOP_SolidSolid.hxx>
12 #include <BOP_ShellSolid.hxx>
13 #include <BOP_WireWire.hxx>
14 #include <BOP_WireShell.hxx>
15 #include <BOP_WireSolid.hxx>
16 #include <BOPTools_DSFiller.hxx>
17 #include <BOPTools_Tools3D.hxx>
18 #include <BOP_EmptyBuilder.hxx>
19
20 #include <BOP_WireSolidHistoryCollector.hxx>
21 #include <BOP_ShellSolidHistoryCollector.hxx>
22 #include <BOP_SolidSolidHistoryCollector.hxx>
23 #include <BOP_SectionHistoryCollector.hxx>
24 #include <BRepLib_FuseEdges.hxx>
25 #include <TopExp.hxx>
26 #include <TopTools_MapOfShape.hxx>
27 #include <TopTools_ListIteratorOfListOfShape.hxx>
28
29 static Handle(BOP_HistoryCollector) MakeCollector(const TopoDS_Shape&       theShape1,
30                                                   const TopoDS_Shape&       theShape2,
31                                                   const BOP_Operation       theOperation);
32
33
34 //=======================================================================
35 //function : BRepAlgoAPI_BooleanOperation
36 //purpose  : 
37 //=======================================================================
38   BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation(const TopoDS_Shape& aS1, 
39                                                              const TopoDS_Shape& aS2,
40                                                              const BOP_Operation anOp)
41
42   myS1(aS1),
43   myS2(aS2),
44   myBuilderCanWork(Standard_False),
45   myOperation(anOp),
46   myErrorStatus(1),
47   myDSFiller(NULL),
48   myBuilder(NULL),
49   myEntryType(1),
50   myFuseEdges(Standard_False)
51 {
52 }
53 //=======================================================================
54 //function : BRepAlgoAPI_BooleanOperation
55 //purpose  : 
56 //=======================================================================
57   BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation(const TopoDS_Shape& aS1, 
58                                                              const TopoDS_Shape& aS2,
59                                                              const BOPTools_DSFiller& aDSFiller,
60                                                              const BOP_Operation anOp)
61
62   myS1(aS1),
63   myS2(aS2),
64   myBuilderCanWork(Standard_False),
65   myOperation(anOp),
66   myErrorStatus(1),
67   myDSFiller(NULL),
68   myBuilder(NULL),
69   myEntryType(0),
70   myFuseEdges(Standard_False)
71 {
72   if ((Standard_Address) &aDSFiller!=NULL) {
73     myDSFiller=(BOPTools_PDSFiller)&aDSFiller;
74   }
75 }
76 //=======================================================================
77 //function : Destroy
78 //purpose  : 
79 //=======================================================================
80   void BRepAlgoAPI_BooleanOperation::Destroy()
81 {
82   if (myBuilder!=NULL) {
83     delete myBuilder;
84     myBuilder=NULL;
85   }
86   if (myDSFiller!=NULL && myEntryType) {
87     delete myDSFiller;
88     myDSFiller=NULL;
89   }
90 }
91 //=======================================================================
92 //function : SetOperation
93 //purpose  : 
94 //=======================================================================
95   void BRepAlgoAPI_BooleanOperation::SetOperation (const BOP_Operation anOp)
96 {
97   myOperation=anOp;
98 }
99 //=======================================================================
100 //function : Operation
101 //purpose  : 
102 //=======================================================================
103   BOP_Operation BRepAlgoAPI_BooleanOperation::Operation ()const
104 {
105   return myOperation;
106 }
107
108 //=======================================================================
109 //function : FuseEdges
110 //purpose  : 
111 //=======================================================================
112   Standard_Boolean BRepAlgoAPI_BooleanOperation::FuseEdges ()const
113 {
114   return myFuseEdges;
115 }
116
117 //=======================================================================
118 //function : Shape1
119 //purpose  : 
120 //=======================================================================
121   const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape1() const 
122 {
123   return myS1;
124 }
125
126 //=======================================================================
127 //function : Shape2
128 //purpose  : 
129 //=======================================================================
130   const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape2() const 
131 {
132   return myS2;
133 }
134
135 //=======================================================================
136 //function : BuilderCanWork
137 //purpose  : 
138 //=======================================================================
139   Standard_Boolean BRepAlgoAPI_BooleanOperation::BuilderCanWork() const
140 {
141   return myBuilderCanWork;
142 }
143 //=======================================================================
144 //function : ErrorStatus
145 //purpose  : 
146 //=======================================================================
147   Standard_Integer BRepAlgoAPI_BooleanOperation::ErrorStatus()const
148 {
149   return myErrorStatus;    
150 }
151 //=======================================================================
152 //function : Modified
153 //purpose  : 
154 //=======================================================================
155 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified(const TopoDS_Shape& aS) 
156 {
157   if (myBuilder==NULL) {
158     myGenerated.Clear();
159     return myGenerated;
160   }
161   else {
162     const TopTools_ListOfShape& aLM=myBuilder->Modified(aS);
163
164     if(myFuseEdges) {
165       return RefinedList(aLM);
166     }
167
168     return aLM;
169   }
170 }
171
172 //=======================================================================
173 //function : IsDeleted
174 //purpose  : 
175 //=======================================================================
176   Standard_Boolean BRepAlgoAPI_BooleanOperation::IsDeleted(const TopoDS_Shape& aS) 
177 {
178
179 //   Standard_Boolean bDeleted = Standard_True; 
180 //   if (myBuilder==NULL) {
181 //     return bDeleted; 
182 //   }
183 //   else {
184 //     bDeleted=myBuilder->IsDeleted(aS);
185 //     return bDeleted;    
186 //   }
187   if(myHistory.IsNull()) {
188     Standard_Boolean bDeleted = Standard_True; 
189
190     if (myBuilder==NULL) {
191       return bDeleted; 
192     }
193     else {
194       bDeleted = myBuilder->IsDeleted(aS);
195       return bDeleted;    
196     }
197   }
198   return myHistory->IsDeleted(aS);
199 }
200 //=======================================================================
201 //function : PrepareFiller
202 //purpose  : 
203 //=======================================================================
204   Standard_Boolean BRepAlgoAPI_BooleanOperation::PrepareFiller()
205 {
206   Standard_Boolean bIsNewFiller=Standard_False;
207   myErrorStatus=1;
208   //
209   if (myS1.IsNull() || myS2.IsNull()) {
210     myErrorStatus=2;
211     return bIsNewFiller;
212   }
213   //
214   if (myOperation==BOP_UNKNOWN) {
215     myErrorStatus=6;
216     return bIsNewFiller;
217   }
218   //
219   if (myDSFiller==NULL) {
220     bIsNewFiller=!bIsNewFiller;
221
222     myDSFiller=new BOPTools_DSFiller;
223     //
224     if (myDSFiller==NULL) {
225       myErrorStatus=4;
226       return bIsNewFiller;
227     }
228     //
229     myDSFiller->SetShapes(myS1, myS2);
230     if (!myDSFiller->IsDone()) {
231       myErrorStatus=3;
232       if (myDSFiller!=NULL) {
233         delete myDSFiller;
234         myDSFiller = NULL;
235         return bIsNewFiller;
236       }
237     }
238   }
239
240   return bIsNewFiller;
241 }
242 //=======================================================================
243 //function : Build
244 //purpose  : 
245 //=======================================================================
246   void BRepAlgoAPI_BooleanOperation::Build()
247 {
248   Standard_Boolean bIsDone, bIsNewFiller;
249   //
250   myBuilderCanWork=Standard_False;
251   NotDone();
252   //
253   bIsNewFiller=PrepareFiller();
254   //
255   if (myErrorStatus!=1) {
256     // there was errors during the preparation 
257     return;
258   }
259   //
260   if (bIsNewFiller) {
261     //Prepare the DS
262     myDSFiller->Perform();
263   }
264   //
265   if (myBuilder!=NULL) {
266     delete myBuilder;
267     myBuilder=NULL;
268   }
269   //
270   const TopoDS_Shape& aS1 = myDSFiller->Shape1();
271   const TopoDS_Shape& aS2 = myDSFiller->Shape2();
272   //
273   myShape.Nullify();
274   // 
275   // SECTION
276   //
277   if (myOperation==BOP_SECTION) {
278     myBuilder=new BOP_Section;
279   }
280   // 
281   // COMMON, FUSE, CUT12, CUT21
282   //
283   else if (myOperation==BOP_COMMON || myOperation==BOP_FUSE ||
284            myOperation==BOP_CUT    || myOperation==BOP_CUT21) {
285     //
286     // Check whether one or both of the arguments is(are) empty shape(s)
287     // If yes, create BOP_EmptyBuilder object and build the result fast.
288     {
289       Standard_Boolean bIsEmptyShape1, bIsEmptyShape2;
290       
291       bIsEmptyShape1=BOPTools_Tools3D::IsEmptyShape(aS1);
292       bIsEmptyShape2=BOPTools_Tools3D::IsEmptyShape(aS2);
293       //
294       if (bIsEmptyShape1 || bIsEmptyShape2) {
295         myBuilder=new BOP_EmptyBuilder;
296         //
297         if (myBuilder==NULL) {
298           myErrorStatus=7;
299           return ;
300         }
301         //
302         myBuilder->SetShapes(aS1, aS2);
303         myBuilder->SetOperation (myOperation);
304         myBuilder->DoWithFiller (*myDSFiller);
305         
306         bIsDone=myBuilder->IsDone();
307         
308         if (bIsDone) {
309           myErrorStatus=0;
310           myBuilderCanWork=Standard_True;
311           myShape=myBuilder->Result();
312           Done(); 
313         }
314         else {
315           myErrorStatus=100+myBuilder->ErrorStatus();
316           NotDone();
317         }
318         return;
319       }
320     }
321     //
322     TopAbs_ShapeEnum aT1, aT2;
323
324     aT1=aS1.ShapeType();
325     aT2=aS2.ShapeType();
326     //
327     // Shell / Shell
328     if (aT1==TopAbs_SHELL && aT2==TopAbs_SHELL) {
329       myBuilder=new BOP_ShellShell;
330     }
331     //
332     // Solid / Solid
333     else if (aT1==TopAbs_SOLID && aT2==TopAbs_SOLID) {
334       myBuilder=new BOP_SolidSolid;
335     }
336     //
337     // Shell / Solid
338     else if ((aT1==TopAbs_SOLID && aT2==TopAbs_SHELL)
339              ||
340              (aT2==TopAbs_SOLID && aT1==TopAbs_SHELL)) {
341       myBuilder=new BOP_ShellSolid;
342     }
343     //
344     // Wire / Wire
345     else if (aT1==TopAbs_WIRE && aT2==TopAbs_WIRE){
346       myBuilder=new BOP_WireWire;
347     }
348     //
349     // Wire / Shell
350     else if ((aT1==TopAbs_WIRE  && aT2==TopAbs_SHELL)
351              ||
352              (aT2==TopAbs_WIRE  && aT1==TopAbs_SHELL)) {
353       myBuilder=new BOP_WireShell;
354     }
355     //
356     // Wire / Shell
357     else if ((aT1==TopAbs_WIRE  && aT2==TopAbs_SOLID)
358              ||
359              (aT2==TopAbs_WIRE  && aT1==TopAbs_SOLID)) {
360       myBuilder=new BOP_WireSolid;
361     }
362     else {
363       myErrorStatus=5;
364       return ;
365     }
366   }
367   //
368   if (myBuilder==NULL) {
369     myErrorStatus=7;
370     return ;
371   }
372   //
373   myBuilder->SetShapes(aS1, aS2);
374   myBuilder->SetOperation (myOperation);
375
376   myHistory = MakeCollector(aS1, aS2, myOperation);
377   myBuilder->SetHistoryCollector(myHistory);
378
379   myBuilder->DoWithFiller (*myDSFiller);
380
381   bIsDone=myBuilder->IsDone();
382   
383   if (bIsDone) {
384     myErrorStatus=0;
385     myBuilderCanWork=Standard_True;
386     myShape=myBuilder->Result();
387     Done(); 
388   }
389   else {
390     myErrorStatus=100+myBuilder->ErrorStatus();
391     NotDone();
392   }
393 }
394
395 //
396 //=======================================================================
397 //function : SectionEdges
398 //purpose  : 
399 //=======================================================================
400 const  TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::SectionEdges()
401 {
402   if (myBuilder==NULL) {
403     myGenerated.Clear();
404     return myGenerated;
405   }
406   else {
407     const TopTools_ListOfShape& aLM=myBuilder->SectionEdges();
408
409     if(myFuseEdges) {
410       return RefinedList(aLM);
411     }
412
413     return aLM;
414   }
415 }
416 //
417
418 // ================================================================================================
419 // function: Modified2
420 // purpose:
421 // ================================================================================================
422 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified2(const TopoDS_Shape& aS) 
423 {
424   if(myHistory.IsNull()) {
425     myGenerated.Clear();
426     return myGenerated;
427   }
428
429   if(myFuseEdges) {
430     const TopTools_ListOfShape& aL = myHistory->Modified(aS);
431     return RefinedList(aL);
432   }
433
434   return myHistory->Modified(aS);
435 }
436
437 // ================================================================================================
438 // function: Generated
439 // purpose:
440 // ================================================================================================
441 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Generated(const TopoDS_Shape& S) 
442 {
443   if(myHistory.IsNull()) {
444     myGenerated.Clear();
445     return myGenerated;
446   }
447  
448   if(myFuseEdges) {
449     const TopTools_ListOfShape& aL = myHistory->Generated(S);
450     return RefinedList(aL);
451   }
452
453   return myHistory->Generated(S);
454 }
455
456 // ================================================================================================
457 // function: HasModified
458 // purpose:
459 // ================================================================================================
460 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasModified() const
461 {
462   if(myHistory.IsNull()) {
463     return Standard_False;
464   }
465   return myHistory->HasModified();
466 }
467
468 // ================================================================================================
469 // function: HasGenerated
470 // purpose:
471 // ================================================================================================
472 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasGenerated() const
473 {
474   if(myHistory.IsNull()) {
475     return Standard_False;
476   }
477   return myHistory->HasGenerated();
478 }
479
480 // ================================================================================================
481 // function: HasDeleted
482 // purpose:
483 // ================================================================================================
484 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasDeleted() const
485 {
486   if(myHistory.IsNull()) {
487     return Standard_False;
488   }
489   return myHistory->HasDeleted();
490 }
491 //=======================================================================
492 //function : RefineEdges
493 //purpose  : 
494 //=======================================================================
495
496   void BRepAlgoAPI_BooleanOperation::RefineEdges ()
497 {
498
499   if(myFuseEdges) return; //Edges have been refined yet
500
501   BRepLib_FuseEdges FE(myShape);
502   FE.SetConcatBSpl(Standard_True);
503
504   // avoid fusing old edges
505   TopTools_IndexedMapOfShape mapOldEdges;
506   TopExp::MapShapes (myS1, TopAbs_EDGE, mapOldEdges);
507   TopExp::MapShapes (myS2, TopAbs_EDGE, mapOldEdges);
508   FE.AvoidEdges (mapOldEdges);
509
510   // Get List of edges that have been fused
511   myFuseEdges = Standard_False;
512   myModifFaces.Clear();
513   myEdgeMap.Clear();
514   TopTools_DataMapOfIntegerListOfShape aFusedEdges;
515
516   FE.Edges(aFusedEdges);
517   Standard_Integer nle = aFusedEdges.Extent();
518   if (nle != 0) {
519     FE.Perform();
520     myShape = FE.Shape();
521
522     TopTools_DataMapOfIntegerShape aResultEdges;
523
524     FE.ResultEdges(aResultEdges);
525     FE.Faces(myModifFaces);
526     myFuseEdges = Standard_True;
527
528     
529     Standard_Integer i;
530     for(i = 1; i <= nle; ++i) {
531       const TopoDS_Shape& aNewE = aResultEdges(i);
532       const TopTools_ListOfShape& aListOfOldEdges = aFusedEdges(i);
533       TopTools_ListIteratorOfListOfShape anIter(aListOfOldEdges);
534       for(; anIter.More(); anIter.Next()) {
535         myEdgeMap.Bind(anIter.Value(), aNewE);
536       }
537     }
538   }
539   
540 }
541
542 //=======================================================================
543 //function : RefinedList
544 //purpose  : 
545 //=======================================================================
546 const TopTools_ListOfShape& 
547   BRepAlgoAPI_BooleanOperation::RefinedList(const TopTools_ListOfShape& theL) 
548 {
549   myGenerated.Clear();
550   TopTools_MapOfShape aMap;
551
552   TopTools_ListIteratorOfListOfShape anIter(theL);
553
554   for(; anIter.More(); anIter.Next()) {
555     const TopoDS_Shape& anS = anIter.Value();
556
557     if(anS.ShapeType() == TopAbs_EDGE) {
558       if(myEdgeMap.IsBound(anS)) {
559         const TopoDS_Shape& aNewEdge = myEdgeMap.Find(anS);
560         if(aMap.Add(aNewEdge)) {
561           myGenerated.Append(aNewEdge);
562         }
563       }
564       else {
565         myGenerated.Append(anS);
566       }
567     }
568     else if (anS.ShapeType() == TopAbs_FACE) {
569       if(myModifFaces.IsBound(anS)) {
570         myGenerated.Append(myModifFaces.Find(anS));
571       }
572       else {
573         myGenerated.Append(anS);
574       }
575     }
576     else {
577       myGenerated.Append(anS);
578     }
579   }
580
581   return myGenerated;
582
583 }
584 // -----------------------------------------------------------------------------------------
585 // static function: MakeCollector
586 // purpose:
587 // -----------------------------------------------------------------------------------------
588 Handle(BOP_HistoryCollector) MakeCollector(const TopoDS_Shape&       theShape1,
589                                            const TopoDS_Shape&       theShape2,
590                                            const BOP_Operation       theOperation) {
591
592   Handle(BOP_HistoryCollector) aresult;
593
594   if(theOperation == BOP_SECTION) {
595     aresult = new BOP_SectionHistoryCollector(theShape1, theShape2);
596     return aresult;
597   }
598
599   TopAbs_ShapeEnum aT1, aT2;
600
601   aT1 = theShape1.ShapeType();
602   aT2 = theShape2.ShapeType();
603   //
604   // Shell / Shell
605   if (aT1==TopAbs_SHELL && aT2==TopAbs_SHELL) {
606     //     aresult = new BOP_ShellShellHistoryCollector(theShape1, theShape2, theOperation, theDSFiller);
607   }
608   //
609   // Solid / Solid
610   else if (aT1==TopAbs_SOLID && aT2==TopAbs_SOLID) {
611     aresult = new BOP_SolidSolidHistoryCollector(theShape1, theShape2, theOperation);
612   }
613   //
614   // Shell / Solid
615   else if ((aT1==TopAbs_SOLID && aT2==TopAbs_SHELL)
616            ||
617            (aT2==TopAbs_SOLID && aT1==TopAbs_SHELL)) {
618     aresult = new BOP_ShellSolidHistoryCollector(theShape1, theShape2, theOperation);
619   }
620   //
621   // Wire / Wire
622   else if (aT1==TopAbs_WIRE && aT2==TopAbs_WIRE){
623     //     aresult = new BOP_WireWireHistoryCollector(theShape1, theShape2, theOperation, theDSFiller);
624   }
625   //
626   // Wire / Shell
627   else if ((aT1==TopAbs_WIRE  && aT2==TopAbs_SHELL)
628            ||
629            (aT2==TopAbs_WIRE  && aT1==TopAbs_SHELL)) {
630     //     aresult = new BOP_WireShellHistoryCollector(theShape1, theShape2, theOperation, theDSFiller);
631   }
632   //
633   // Wire / Shell
634   else if ((aT1==TopAbs_WIRE  && aT2==TopAbs_SOLID)
635            ||
636            (aT2==TopAbs_WIRE  && aT1==TopAbs_SOLID)) {
637     aresult = new BOP_WireSolidHistoryCollector(theShape1, theShape2, theOperation);
638   }
639   return aresult;
640 }
641