0023024: Update headers of OCCT files
[occt.git] / src / BRepAlgoAPI / BRepAlgoAPI_BooleanOperation.cxx
CommitLineData
b311480e 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
7fd59977 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
45static 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//=======================================================================
171const 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//=======================================================================
416const 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// ================================================================================================
438const 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// ================================================================================================
457const 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// ================================================================================================
476Standard_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// ================================================================================================
488Standard_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// ================================================================================================
500Standard_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//=======================================================================
562const 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// -----------------------------------------------------------------------------------------
604Handle(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