Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepAlgoAPI / BRepAlgoAPI_BooleanOperation.cxx
CommitLineData
7fd59977 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
29static 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//=======================================================================
155const 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//=======================================================================
400const 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// ================================================================================================
422const 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// ================================================================================================
441const 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// ================================================================================================
460Standard_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// ================================================================================================
472Standard_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// ================================================================================================
484Standard_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//=======================================================================
546const 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// -----------------------------------------------------------------------------------------
588Handle(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