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