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