0025477: Boolean Operations with additional tolerance - Fuzzy Boolean operations
[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-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 #include <BRepAlgoAPI_BooleanOperation.ixx>
18
19 #include <TopExp.hxx>
20
21 #include <TopTools_IndexedMapOfShape.hxx>
22 #include <TopTools_DataMapOfIntegerListOfShape.hxx>
23 #include <TopTools_DataMapOfIntegerShape.hxx>
24 #include <TopTools_ListIteratorOfListOfShape.hxx>
25 #include <TopTools_MapOfShape.hxx>
26
27 #include <BRepAlgoAPI_Check.hxx>
28 #include <BRepAlgoAPI.hxx>
29 #include <BRepLib_FuseEdges.hxx>
30
31 #include <BOPDS_PDS.hxx>
32 #include <BOPDS_DS.hxx>
33 #include <BOPDS_VectorOfCurve.hxx>
34 #include <BOPDS_Interf.hxx>
35 #include <BOPDS_Curve.hxx>
36 #include <BOPDS_ListOfPaveBlock.hxx>
37
38 #include <BOPAlgo_PaveFiller.hxx>
39 #include <BOPAlgo_BOP.hxx>
40 #include <BOPAlgo_Section.hxx>
41
42 //=======================================================================
43 //function : BRepAlgoAPI_BooleanOperation
44 //purpose  : 
45 //=======================================================================
46 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation()
47 :
48   BRepAlgoAPI_BuilderAlgo(), 
49   myOperation(BOPAlgo_UNKNOWN),
50   myEntryType(1),
51   myBuilderCanWork(Standard_False),
52   myFuseEdges(Standard_False)
53 {
54 }
55 //=======================================================================
56 //function : BRepAlgoAPI_BooleanOperation
57 //purpose  : 
58 //=======================================================================
59 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation
60   (const TopoDS_Shape& aS1, 
61    const TopoDS_Shape& aS2,
62    const BOPAlgo_Operation anOp)
63
64   BRepAlgoAPI_BuilderAlgo(),
65   myS1(aS1),
66   myS2(aS2),
67   myOperation(anOp),
68   myEntryType(1),
69   myBuilderCanWork(Standard_False),
70   myFuseEdges(Standard_False)
71 {
72 }
73 //=======================================================================
74 //function : BRepAlgoAPI_BooleanOperation
75 //purpose  : 
76 //=======================================================================
77 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation
78   (const TopoDS_Shape& aS1, 
79    const TopoDS_Shape& aS2,
80    const BOPAlgo_PaveFiller& aPF,
81    const BOPAlgo_Operation anOp)
82
83   BRepAlgoAPI_BuilderAlgo(),
84   myS1(aS1),
85   myS2(aS2),
86   myOperation(anOp),
87   myEntryType(0),
88   myBuilderCanWork(Standard_False),
89   myFuseEdges(Standard_False)
90 {
91   myDSFiller=(BOPAlgo_PaveFiller*)&aPF;
92 }
93 //=======================================================================
94 //function : ~
95 //purpose  : 
96 //=======================================================================
97 BRepAlgoAPI_BooleanOperation::~BRepAlgoAPI_BooleanOperation()
98 {
99   if (myBuilder) {
100     delete myBuilder;
101     myBuilder=NULL;
102   }
103   if (myDSFiller && myEntryType) {
104     delete myDSFiller;
105     myDSFiller=NULL;
106   }
107   //
108   myModifFaces.Clear();
109   myEdgeMap.Clear();
110 }
111 //=======================================================================
112 //function : SetOperation
113 //purpose  : 
114 //=======================================================================
115 void BRepAlgoAPI_BooleanOperation::SetOperation 
116   (const BOPAlgo_Operation anOp)
117 {
118   myOperation=anOp;
119 }
120 //=======================================================================
121 //function : Operation
122 //purpose  : 
123 //=======================================================================
124 BOPAlgo_Operation BRepAlgoAPI_BooleanOperation::Operation ()const
125 {
126   return myOperation;
127 }
128 //=======================================================================
129 //function : SetShape1
130 //purpose  : 
131 //=======================================================================
132 void  BRepAlgoAPI_BooleanOperation::SetShape1(const TopoDS_Shape& aS) 
133 {
134   myS1=aS;
135
136 //=======================================================================
137 //function : SetShape2
138 //purpose  : 
139 //=======================================================================
140 void  BRepAlgoAPI_BooleanOperation::SetShape2(const TopoDS_Shape& aS) 
141 {
142   myS2=aS;
143
144 //=======================================================================
145 //function : Shape1
146 //purpose  : 
147 //=======================================================================
148 const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape1() const 
149 {
150   return myS1;
151 }
152 //=======================================================================
153 //function : Shape2
154 //purpose  : 
155 //=======================================================================
156 const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape2() const 
157 {
158   return myS2;
159 }
160 //=======================================================================
161 //function : BuilderCanWork
162 //purpose  : 
163 //=======================================================================
164   Standard_Boolean BRepAlgoAPI_BooleanOperation::BuilderCanWork() const
165 {
166   return myBuilderCanWork;
167 }
168 //=======================================================================
169 //function : FuseEdges
170 //purpose  : 
171 //=======================================================================
172 Standard_Boolean BRepAlgoAPI_BooleanOperation::FuseEdges ()const
173 {
174   return myFuseEdges;
175 }
176 //=======================================================================
177 //function : PrepareFiller
178 //purpose  : 
179 //=======================================================================
180 Standard_Boolean BRepAlgoAPI_BooleanOperation::PrepareFiller()
181 {
182   Standard_Boolean bIsNewFiller=Standard_False;
183   myErrorStatus=1;
184   //
185   if (myS1.IsNull() || myS2.IsNull()) {
186     myErrorStatus=2;
187     return bIsNewFiller;
188   }
189   //
190   if (myOperation==BOPAlgo_UNKNOWN) {
191     myErrorStatus=6;
192     return bIsNewFiller;
193   }
194   //
195   if (myDSFiller==NULL) {
196     bIsNewFiller=!bIsNewFiller;
197
198     myDSFiller=new BOPAlgo_PaveFiller;
199     //
200     if (myDSFiller==NULL) {
201       myErrorStatus=4;
202       return bIsNewFiller;
203     }
204     //
205     BOPCol_ListOfShape aLS;
206     aLS.Append(myS1);
207     aLS.Append(myS2);
208     //
209     myDSFiller->SetArguments(aLS);
210     myDSFiller->SetRunParallel(myRunParallel);
211     myDSFiller->SetProgressIndicator(myProgressIndicator);
212     myDSFiller->SetFuzzyValue(myFuzzyValue);
213   }
214
215   return bIsNewFiller;
216 }
217 //=======================================================================
218 //function : Build
219 //purpose  : 
220 //=======================================================================
221 void BRepAlgoAPI_BooleanOperation::Build()
222 {
223   Standard_Boolean bIsNewFiller;
224   Standard_Integer iErr;
225   //
226   //dump arguments and result of boolean operation in tcl script
227   char *pathdump = getenv("CSF_DEBUG_BOP");
228   Standard_Boolean isDump = (pathdump != NULL),
229                    isDumpArgs = Standard_False,
230                    isDumpRes = Standard_False;
231   Standard_CString aPath = pathdump;
232   //
233   myBuilderCanWork=Standard_False;
234   NotDone();
235   //
236   bIsNewFiller=PrepareFiller();
237   //
238   if (myErrorStatus!=1) {
239     // there was errors during the preparation 
240     return;
241   }
242   //
243   if (bIsNewFiller) {
244     //Prepare the DS
245     myDSFiller->Perform();
246   }
247   //
248   if (myBuilder!=NULL) {
249     delete myBuilder;
250     myBuilder=NULL;
251   }
252   //
253   const TopoDS_Shape& aS1 = myS1;
254   const TopoDS_Shape& aS2 = myS2;
255   //
256   if (isDump) {
257     BRepAlgoAPI_Check aChekArgs(aS1, aS2, myOperation);
258     isDumpArgs = !aChekArgs.IsValid();
259   }
260   //
261   myShape.Nullify();
262   //
263   if (myOperation==BOPAlgo_SECTION) {
264     myBuilder=new BOPAlgo_Section;
265     myBuilder->AddArgument(aS1);
266     myBuilder->AddArgument(aS2);
267   }
268   else {
269     BOPAlgo_BOP *pBOP;
270     //
271     pBOP=new BOPAlgo_BOP;
272     myBuilder=pBOP;
273     pBOP->AddArgument(aS1);
274     pBOP->AddTool(aS2);
275     pBOP->SetOperation(myOperation);
276   }
277   //
278   myBuilder->SetRunParallel(myRunParallel);
279   myBuilder->SetProgressIndicator(myProgressIndicator);
280   myBuilder->PerformWithFiller(*myDSFiller);
281   iErr = myBuilder->ErrorStatus();
282   if (!iErr) {
283     myErrorStatus=0;
284     myBuilderCanWork=Standard_True;
285     myShape=myBuilder->Shape();
286     //
287     if (isDump) {
288       BRepAlgoAPI_Check aCheckRes(myShape);
289       isDumpRes = !aCheckRes.IsValid();
290       if (isDumpArgs || isDumpRes) {
291         BRepAlgoAPI::DumpOper(aPath, 
292                               aS1, 
293                               aS2, 
294                               myShape, 
295                               myOperation, 
296                               isDumpArgs);
297       }
298     }
299     //
300     Done(); 
301   } 
302   else {
303     myErrorStatus=100+iErr;
304     NotDone();
305   }
306 }
307
308 //=======================================================================
309 //function : RefineEdges
310 //purpose  : 
311 //=======================================================================
312 void BRepAlgoAPI_BooleanOperation::RefineEdges ()
313 {
314   if(myFuseEdges) return; //Edges have been refined yet
315
316   BRepLib_FuseEdges FE(myShape);
317   FE.SetConcatBSpl(Standard_True);
318
319   // avoid fusing old edges
320   TopTools_IndexedMapOfShape mapOldEdges;
321   TopExp::MapShapes (myS1, TopAbs_EDGE, mapOldEdges);
322   TopExp::MapShapes (myS2, TopAbs_EDGE, mapOldEdges);
323   FE.AvoidEdges (mapOldEdges);
324
325   // Get List of edges that have been fused
326   myFuseEdges = Standard_False;
327   myModifFaces.Clear();
328   myEdgeMap.Clear();
329   TopTools_DataMapOfIntegerListOfShape aFusedEdges;
330
331   FE.Edges(aFusedEdges);
332   Standard_Integer nle = aFusedEdges.Extent();
333   if (nle != 0) {
334     FE.Perform();
335     myShape = FE.Shape();
336
337     TopTools_DataMapOfIntegerShape aResultEdges;
338
339     FE.ResultEdges(aResultEdges);
340     FE.Faces(myModifFaces);
341     myFuseEdges = Standard_True;
342     
343     Standard_Integer i;
344     for(i = 1; i <= nle; ++i) {
345       const TopoDS_Shape& aNewE = aResultEdges(i);
346       const TopTools_ListOfShape& aListOfOldEdges = aFusedEdges(i);
347       TopTools_ListIteratorOfListOfShape anIter(aListOfOldEdges);
348       for(; anIter.More(); anIter.Next()) {
349         myEdgeMap.Bind(anIter.Value(), aNewE);
350       }
351     }
352   }
353 }
354 //=======================================================================
355 //function : RefinedList
356 //purpose  : 
357 //=======================================================================
358 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::RefinedList
359   (const TopTools_ListOfShape& theL) 
360 {
361   myGenerated.Clear();
362   TopTools_MapOfShape aMap;
363
364   TopTools_ListIteratorOfListOfShape anIter(theL);
365
366   for(; anIter.More(); anIter.Next()) {
367     const TopoDS_Shape& anS = anIter.Value();
368
369     if(anS.ShapeType() == TopAbs_EDGE) {
370       if(myEdgeMap.IsBound(anS)) {
371         const TopoDS_Shape& aNewEdge = myEdgeMap.Find(anS);
372         if(aMap.Add(aNewEdge)) {
373           myGenerated.Append(aNewEdge);
374         }
375       }
376       else {
377         myGenerated.Append(anS);
378       }
379     }
380     else if (anS.ShapeType() == TopAbs_FACE) {
381       if(myModifFaces.IsBound(anS)) {
382         myGenerated.Append(myModifFaces.Find(anS));
383       }
384       else {
385         myGenerated.Append(anS);
386       }
387     }
388     else {
389       myGenerated.Append(anS);
390     }
391   }
392
393   return myGenerated;
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   //
407   Standard_Integer aNb, i, j, aNbCurves, nE;
408   BOPDS_ListIteratorOfListOfPaveBlock anIt;
409   //
410   const BOPDS_PDS& pDS = myDSFiller->PDS();
411   BOPDS_VectorOfInterfFF& aFFs=pDS->InterfFF();
412   myGenerated.Clear();
413   //
414   aNb=aFFs.Extent();
415   for (i = 0; i < aNb; i++) {
416     BOPDS_InterfFF& aFFi=aFFs(i);
417     const BOPDS_VectorOfCurve& aSeqOfCurve=aFFi.Curves();
418     //
419     aNbCurves=aSeqOfCurve.Extent();
420     for (j=0; j<aNbCurves; j++) {
421       const BOPDS_Curve& aCurve=aSeqOfCurve(j);
422       const BOPDS_ListOfPaveBlock& aSectEdges = aCurve.PaveBlocks();
423       //
424       anIt.Initialize(aSectEdges);
425       for(; anIt.More(); anIt.Next()) {
426         const Handle(BOPDS_PaveBlock)& aPB = anIt.Value();
427         nE = aPB->Edge();
428         const TopoDS_Shape& aE = pDS->Shape(nE);
429         myGenerated.Append(aE);
430       }
431     }
432   }
433   //
434   if(myFuseEdges) {
435     TopTools_ListOfShape theLS;
436     theLS.Assign(myGenerated);
437     //
438     RefinedList(theLS);
439   }
440   //
441   return myGenerated;
442 }
443 //=======================================================================
444 //function : Generated
445 //purpose  : 
446 //=======================================================================
447 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Generated
448   (const TopoDS_Shape& S) 
449 {
450   if (myBuilder==NULL) {
451     myGenerated.Clear();
452     return myGenerated;
453   }
454   //
455   if(myFuseEdges) {
456     const TopTools_ListOfShape& aL = myBuilder->Generated(S);
457     return RefinedList(aL);
458   }
459   
460   return myBuilder->Generated(S);
461 }
462
463 //=======================================================================
464 //function : Modified
465 //purpose  : 
466 //=======================================================================
467 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified
468   (const TopoDS_Shape& aS) 
469 {
470   if (myBuilder==NULL) {
471     myGenerated.Clear();
472     return myGenerated;
473   }
474   else {
475     myGenerated = myBuilder->Modified(aS);
476
477     if(myFuseEdges) {
478       TopTools_ListOfShape theLS;
479       theLS.Assign(myGenerated);
480       //
481       RefinedList(theLS);
482     }
483     return myGenerated;
484   }
485 }
486 //=======================================================================
487 //function : IsDeleted
488 //purpose  : 
489 //=======================================================================
490 Standard_Boolean BRepAlgoAPI_BooleanOperation::IsDeleted
491   (const TopoDS_Shape& aS) 
492 {
493   Standard_Boolean bDeleted = Standard_True; 
494   if (myBuilder != NULL) {
495     bDeleted=myBuilder->IsDeleted(aS);
496   }
497   return bDeleted; 
498 }
499 //=======================================================================
500 //function : HasModified
501 //purpose  : 
502 //=======================================================================
503 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasModified() const
504 {
505   if (myBuilder==NULL) {
506     return Standard_False;
507   }
508   return myBuilder->HasModified();
509 }
510 //=======================================================================
511 //function : HasGenerated
512 //purpose  : 
513 //=======================================================================
514 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasGenerated() const
515 {
516   if (myBuilder==NULL) {
517     return Standard_False;
518   }
519   return myBuilder->HasGenerated();
520 }
521 //=======================================================================
522 //function : HasDeleted
523 //purpose  : 
524 //=======================================================================
525 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasDeleted() const
526 {
527   if (myBuilder==NULL) {
528     return Standard_False;
529   }
530   return myBuilder->HasDeleted();
531 }