0023648: Add tool for checking shapes on validity for boolean operations.
[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#include <BRepAlgoAPI_BooleanOperation.ixx>
22
da219023 23#include <BRepAlgoAPI.hxx>
24#include <BRepAlgoAPI_Check.hxx>
25
7fd59977 26#include <BRepLib_FuseEdges.hxx>
27#include <TopExp.hxx>
28#include <TopTools_MapOfShape.hxx>
29#include <TopTools_ListIteratorOfListOfShape.hxx>
30
4e57c75e 31#include <BOPAlgo_PaveFiller.hxx>
32#include <BOPAlgo_BOP.hxx>
33#include <BOPDS_DS.hxx>
7fd59977 34
35//=======================================================================
36//function : BRepAlgoAPI_BooleanOperation
37//purpose :
38//=======================================================================
39 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation(const TopoDS_Shape& aS1,
4e57c75e 40 const TopoDS_Shape& aS2,
41 const BOPAlgo_Operation anOp)
7fd59977 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,
4e57c75e 59 const TopoDS_Shape& aS2,
60 const BOPAlgo_PaveFiller& aDSFiller,
61 const BOPAlgo_Operation anOp)
7fd59977 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) {
4e57c75e 74 myDSFiller=(BOPAlgo_PaveFiller*)&aDSFiller;
7fd59977 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 }
4e57c75e 91
92 //
93 myModifFaces.Clear();
94 myEdgeMap.Clear();
7fd59977 95}
96//=======================================================================
97//function : SetOperation
98//purpose :
99//=======================================================================
4e57c75e 100 void BRepAlgoAPI_BooleanOperation::SetOperation (const BOPAlgo_Operation anOp)
7fd59977 101{
102 myOperation=anOp;
103}
104//=======================================================================
105//function : Operation
106//purpose :
107//=======================================================================
4e57c75e 108 BOPAlgo_Operation BRepAlgoAPI_BooleanOperation::Operation ()const
7fd59977 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//=======================================================================
160const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified(const TopoDS_Shape& aS)
161{
162 if (myBuilder==NULL) {
163 myGenerated.Clear();
164 return myGenerated;
165 }
166 else {
4e57c75e 167 myGenerated = myBuilder->Modified(aS);
7fd59977 168
169 if(myFuseEdges) {
4e57c75e 170 TopTools_ListOfShape theLS;
171 theLS.Assign(myGenerated);
172 //
173 RefinedList(theLS);
7fd59977 174 }
4e57c75e 175 return myGenerated;
7fd59977 176 }
177}
178
179//=======================================================================
180//function : IsDeleted
181//purpose :
182//=======================================================================
183 Standard_Boolean BRepAlgoAPI_BooleanOperation::IsDeleted(const TopoDS_Shape& aS)
184{
4e57c75e 185 Standard_Boolean bDeleted = Standard_True;
186 if (myBuilder != NULL) {
187 bDeleted=myBuilder->IsDeleted(aS);
7fd59977 188 }
4e57c75e 189 return bDeleted;
7fd59977 190}
4e57c75e 191
7fd59977 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 //
4e57c75e 206 if (myOperation==BOPAlgo_UNKNOWN) {
7fd59977 207 myErrorStatus=6;
208 return bIsNewFiller;
209 }
210 //
211 if (myDSFiller==NULL) {
212 bIsNewFiller=!bIsNewFiller;
213
4e57c75e 214 myDSFiller=new BOPAlgo_PaveFiller;
7fd59977 215 //
216 if (myDSFiller==NULL) {
217 myErrorStatus=4;
218 return bIsNewFiller;
219 }
220 //
4e57c75e 221 BOPCol_ListOfShape aLS;
222 aLS.Append(myS1);
223 aLS.Append(myS2);
224 //
225 myDSFiller->SetArguments(aLS);
7fd59977 226 }
227
228 return bIsNewFiller;
229}
230//=======================================================================
231//function : Build
232//purpose :
233//=======================================================================
234 void BRepAlgoAPI_BooleanOperation::Build()
235{
4e57c75e 236 Standard_Boolean bIsNewFiller;
237 Standard_Integer iErr;
7fd59977 238 //
da219023 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 //
7fd59977 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 //
4e57c75e 266 const TopoDS_Shape& aS1 = myS1;
267 const TopoDS_Shape& aS2 = myS2;
7fd59977 268 //
da219023 269 if (isDump) {
270 BRepAlgoAPI_Check aChekArgs(aS1, aS2, myOperation);
271 isDumpArgs = !aChekArgs.IsValid();
272 }
273 //
7fd59977 274 myShape.Nullify();
7fd59977 275
4e57c75e 276 myBuilder=new BOPAlgo_BOP;
277 myBuilder->AddArgument(aS1);
278 myBuilder->AddTool(aS2);
279 myBuilder->SetOperation(myOperation);
7fd59977 280 //
4e57c75e 281 myBuilder->PerformWithFiller(*myDSFiller);
282 iErr = myBuilder->ErrorStatus();
283 if (!iErr) {
7fd59977 284 myErrorStatus=0;
285 myBuilderCanWork=Standard_True;
4e57c75e 286 myShape=myBuilder->Shape();
da219023 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 //
7fd59977 296 Done();
4e57c75e 297 }
7fd59977 298 else {
4e57c75e 299 myErrorStatus=100+iErr;
7fd59977 300 NotDone();
301 }
302}
303
304//
305//=======================================================================
306//function : SectionEdges
307//purpose :
308//=======================================================================
309const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::SectionEdges()
310{
311 if (myBuilder==NULL) {
312 myGenerated.Clear();
313 return myGenerated;
314 }
4e57c75e 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 }
7fd59977 340 }
7fd59977 341 }
4e57c75e 342 //
343 if(myFuseEdges) {
344 TopTools_ListOfShape theLS;
345 theLS.Assign(myGenerated);
346 //
347 RefinedList(theLS);
348 }
349 //
350 return myGenerated;
7fd59977 351}
7fd59977 352
353// ================================================================================================
354// function: Modified2
355// purpose:
356// ================================================================================================
357const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified2(const TopoDS_Shape& aS)
358{
4e57c75e 359 if (myBuilder==NULL) {
7fd59977 360 myGenerated.Clear();
361 return myGenerated;
362 }
4e57c75e 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);
7fd59977 373 }
4e57c75e 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;
7fd59977 387}
388
389// ================================================================================================
390// function: Generated
391// purpose:
392// ================================================================================================
393const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Generated(const TopoDS_Shape& S)
394{
4e57c75e 395 if (myBuilder==NULL) {
7fd59977 396 myGenerated.Clear();
397 return myGenerated;
398 }
4e57c75e 399 //
7fd59977 400 if(myFuseEdges) {
4e57c75e 401 const TopTools_ListOfShape& aL = myBuilder->Generated(S);
7fd59977 402 return RefinedList(aL);
403 }
4e57c75e 404
405 return myBuilder->Generated(S);
7fd59977 406}
407
408// ================================================================================================
409// function: HasModified
410// purpose:
411// ================================================================================================
412Standard_Boolean BRepAlgoAPI_BooleanOperation::HasModified() const
413{
4e57c75e 414 if (myBuilder==NULL) {
7fd59977 415 return Standard_False;
416 }
4e57c75e 417 return myBuilder->HasModified();
7fd59977 418}
419
420// ================================================================================================
421// function: HasGenerated
422// purpose:
423// ================================================================================================
424Standard_Boolean BRepAlgoAPI_BooleanOperation::HasGenerated() const
425{
4e57c75e 426 if (myBuilder==NULL) {
7fd59977 427 return Standard_False;
428 }
4e57c75e 429 return myBuilder->HasGenerated();
7fd59977 430}
431
432// ================================================================================================
433// function: HasDeleted
434// purpose:
435// ================================================================================================
436Standard_Boolean BRepAlgoAPI_BooleanOperation::HasDeleted() const
437{
4e57c75e 438 if (myBuilder==NULL) {
7fd59977 439 return Standard_False;
440 }
4e57c75e 441 return myBuilder->HasDeleted();
7fd59977 442}
443//=======================================================================
444//function : RefineEdges
445//purpose :
446//=======================================================================
447
448 void BRepAlgoAPI_BooleanOperation::RefineEdges ()
449{
7fd59977 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;
7fd59977 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()) {
4e57c75e 485 myEdgeMap.Bind(anIter.Value(), aNewE);
7fd59977 486 }
487 }
488 }
7fd59977 489}
490
491//=======================================================================
492//function : RefinedList
493//purpose :
494//=======================================================================
495const 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)) {
4e57c75e 508 const TopoDS_Shape& aNewEdge = myEdgeMap.Find(anS);
509 if(aMap.Add(aNewEdge)) {
510 myGenerated.Append(aNewEdge);
511 }
7fd59977 512 }
513 else {
4e57c75e 514 myGenerated.Append(anS);
7fd59977 515 }
516 }
517 else if (anS.ShapeType() == TopAbs_FACE) {
518 if(myModifFaces.IsBound(anS)) {
4e57c75e 519 myGenerated.Append(myModifFaces.Find(anS));
7fd59977 520 }
521 else {
4e57c75e 522 myGenerated.Append(anS);
7fd59977 523 }
524 }
525 else {
526 myGenerated.Append(anS);
527 }
528 }
529
530 return myGenerated;
531
532}