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