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