1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <BOPAlgo_BOP.ixx>
17 #include <TopAbs_ShapeEnum.hxx>
19 #include <TopoDS_Compound.hxx>
20 #include <TopoDS_Iterator.hxx>
21 #include <BRep_Builder.hxx>
22 #include <TopExp_Explorer.hxx>
24 #include <BOPTools.hxx>
25 #include <BOPTools_AlgoTools.hxx>
26 #include <BOPTools_AlgoTools3D.hxx>
28 #include <BOPCol_ListOfShape.hxx>
29 #include <BOPAlgo_BuilderSolid.hxx>
30 #include <TopoDS_Edge.hxx>
33 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
35 //=======================================================================
38 //=======================================================================
39 BOPAlgo_BOP::BOPAlgo_BOP()
43 myMapTools(100, myAllocator)
48 //=======================================================================
51 //=======================================================================
52 BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator)
54 BOPAlgo_Builder(theAllocator),
56 myMapTools(100, myAllocator)
61 //=======================================================================
64 //=======================================================================
65 BOPAlgo_BOP::~BOPAlgo_BOP()
68 //=======================================================================
71 //=======================================================================
72 void BOPAlgo_BOP::Clear()
74 myOperation=BOPAlgo_UNKNOWN;
80 BOPAlgo_Builder::Clear();
82 //=======================================================================
83 //function : AddArgument
85 //=======================================================================
86 void BOPAlgo_BOP::AddArgument(const TopoDS_Shape& theShape)
88 if (myMapFence.Add(theShape)) {
89 myArguments.Append(theShape);
93 //=======================================================================
96 //=======================================================================
97 void BOPAlgo_BOP::AddTool(const TopoDS_Shape& theShape)
99 if (myMapTools.Add(theShape)) {
100 myTools.Append(theShape);
103 if (myMapFence.Add(theShape)) {
104 myArguments.Append(theShape);
108 //=======================================================================
111 //=======================================================================
112 const TopoDS_Shape& BOPAlgo_BOP::Object()const
116 //=======================================================================
119 //=======================================================================
120 const TopoDS_Shape& BOPAlgo_BOP::Tool()const
124 //=======================================================================
125 //function : SetOperation
127 //=======================================================================
128 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
130 myOperation=theOperation;
132 //=======================================================================
133 //function : Operation
135 //=======================================================================
136 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
140 //=======================================================================
141 //function : CheckData
143 //=======================================================================
144 void BOPAlgo_BOP::CheckData()
146 Standard_Integer i, aNb;
147 Standard_Boolean bFlag;
151 aNb=myArguments.Extent();
153 if (aNb!=1 || !(myArgs[0].IsSame(myArgs[1]))) {
154 myErrorStatus=10; // invalid number of arguments
164 myErrorStatus=myPaveFiller->ErrorStatus();
169 for (i=0; i<myNbArgs; ++i) {
170 if (myArgs[i].IsNull()) {
171 myErrorStatus=11; // argument is null shape
176 for (i=0; i<myNbArgs; ++i) {
177 bFlag = BOPTools_AlgoTools3D::IsEmptyShape(myArgs[i]);
183 for (i=0; i<myNbArgs; ++i) {
184 myDims[i]=BOPTools_AlgoTools::Dimension(myArgs[i]);
186 myErrorStatus=13; // non-homogenious argument
191 if (myOperation==BOPAlgo_UNKNOWN) {
192 myErrorStatus=14; // non-licit operation
195 else if (myDims[0]<myDims[1]) {
196 if (myOperation==BOPAlgo_FUSE ||
197 myOperation==BOPAlgo_CUT21) {
198 myErrorStatus=14; // non-licit operation for the arguments
202 else if (myDims[0]>myDims[1]) {
203 if (myOperation==BOPAlgo_FUSE ||
204 myOperation==BOPAlgo_CUT) {
205 myErrorStatus=14; // non-licit operation for the arguments
210 //=======================================================================
213 //=======================================================================
214 void BOPAlgo_BOP::Prepare()
219 BOPAlgo_Builder::Prepare();
221 if(myWarningStatus == 2) {
222 switch(myOperation) {
224 for ( i = 0; i < myNbArgs; i++ ) {
225 aBB.Add(myShape, myArgs[i]);
229 case BOPAlgo_SECTION:
232 if(BOPTools_AlgoTools3D::IsEmptyShape(myArgs[0])) {
235 aBB.Add(myShape, myArgs[0]);
239 if(BOPTools_AlgoTools3D::IsEmptyShape(myArgs[1])) {
242 aBB.Add(myShape, myArgs[1]);
250 //=======================================================================
251 //function : PerformInternal
253 //=======================================================================
254 void BOPAlgo_BOP::PerformInternal(const BOPAlgo_PaveFiller& theFiller)
259 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
260 myDS=myPaveFiller->PDS();
261 myContext=myPaveFiller->Context();
265 if (myErrorStatus && !myWarningStatus) {
274 if(myWarningStatus == 2) {
280 FillImagesVertices();
285 BuildResult(TopAbs_VERTEX);
295 BuildResult(TopAbs_EDGE);
299 //-------------------------------- SECTION f
300 if (myOperation==BOPAlgo_SECTION) {
306 //-------------------------------- SECTION t
309 FillImagesContainers(TopAbs_WIRE);
314 BuildResult(TopAbs_WIRE);
325 BuildResult(TopAbs_FACE);
331 FillImagesContainers(TopAbs_SHELL);
336 BuildResult(TopAbs_SHELL);
346 BuildResult(TopAbs_SOLID);
351 FillImagesContainers(TopAbs_COMPSOLID);
356 BuildResult(TopAbs_COMPSOLID);
361 FillImagesCompounds();
366 BuildResult(TopAbs_COMPOUND);
381 //=======================================================================
382 //function : BuildShape
384 //=======================================================================
385 void BOPAlgo_BOP::BuildShape()
387 Standard_Integer aDmin, aNbLCB;
388 TopAbs_ShapeEnum aT1, aT2, aTR;
389 TopoDS_Shape aR, aRC;
392 BOPCol_ListOfShape aLCB;
393 BOPCol_ListIteratorOfListOfShape aItLCB;
401 if (myDims[0]<myDims[1]) {
410 else if (aDmin==1 || aDmin==2) { //edges, faces
420 BOPTools_AlgoTools::MakeConnexityBlocks(myRC, aT1, aT2, aLCB);
421 aNbLCB=aLCB.Extent();
427 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
429 aItLCB.Initialize(aLCB);
430 for (; aItLCB.More(); aItLCB.Next()) {
431 BOPTools_AlgoTools::MakeContainer(aTR, aR);
433 const TopoDS_Shape& aCB=aItLCB.Value();
435 for (; aIt.More(); aIt.Next()) {
436 const TopoDS_Shape& aS=aIt.Value();
440 if (aTR==TopAbs_SHELL) {
441 BOPTools_AlgoTools::OrientFacesOnShell(aR);
447 }// elase if (aDmin==1 || aDmin==2) {
450 if (myOperation==BOPAlgo_FUSE) {
458 //=======================================================================
461 //=======================================================================
462 void BOPAlgo_BOP::BuildRC()
464 Standard_Boolean bFlag;
465 Standard_Integer i, aDmin, aNb[2], iX = 0, iY = 0;
466 TopAbs_ShapeEnum aTmin;
467 TopoDS_Compound aC, aCS[2];
469 TopExp_Explorer aExp;
470 BOPCol_ListIteratorOfListOfShape aItIm;
471 BOPCol_IndexedMapOfShape aMS[2];
472 BOPCol_IndexedMapOfShape aMSV[2];
477 if (myOperation==BOPAlgo_FUSE) {
478 aBB.MakeCompound(aC);
479 aTmin=TypeToExplore(myDims[0]);
480 aExp.Init(myShape, aTmin);
481 for (; aExp.More(); aExp.Next()) {
482 const TopoDS_Shape& aS=aExp.Current();
491 // 1. Compounds CS that consist of an Arg or Images of the Arg
492 for (i=0; i<myNbArgs; ++i) {
493 aBB.MakeCompound(aCS[i]);
494 const TopoDS_Shape& aS=myArgs[i];
495 if (myImages.IsBound(aS)){
496 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
497 aItIm.Initialize(aLSIm);
498 for (; aItIm.More(); aItIm.Next()) {
499 const TopoDS_Shape& aSIm=aItIm.Value();
500 aBB.Add(aCS[i], aSIm);
509 if (myDims[0]<myDims[1]) {
512 aTmin=TypeToExplore(aDmin);
513 for (i=0; i<myNbArgs; ++i) {
514 aExp.Init(aCS[i], aTmin);
515 for (; aExp.More(); aExp.Next()) {
516 const TopoDS_Shape aS=aExp.Current();
517 if (aTmin == TopAbs_EDGE) {
518 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aS));
519 if (BRep_Tool::Degenerated(aE)) {
520 TopExp_Explorer aExpE(aE, TopAbs_VERTEX);
521 TopoDS_Shape aS1 = aExpE.Current();
522 if (myImages.IsBound(aS1)){
523 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS1);
524 const TopoDS_Shape& aSIm=aLSIm.First();
532 if (myImages.IsBound(aS)){
533 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
534 aItIm.Initialize(aLSIm);
535 for (; aItIm.More(); aItIm.Next()) {
536 const TopoDS_Shape& aSIm=aItIm.Value();
544 aNb[i]=aMS[i].Extent();
547 aBB.MakeCompound(aC);
549 // 3. Find common parts
550 if (myOperation==BOPAlgo_COMMON) {
551 if (myDims[0]==myDims[1]) {
552 iX=(aNb[0]>aNb[1])? 1 : 0;
554 iX=(myDims[0]<myDims[1]) ? 0 : 1;
558 else if (myOperation==BOPAlgo_CUT) {
562 else if (myOperation==BOPAlgo_CUT21) {
566 for (i=1; i<=aNb[iX]; ++i) {
567 const TopoDS_Shape& aSx=aMS[iX].FindKey(i);
568 bFlag=aMS[iY].Contains(aSx);
569 if (aTmin == TopAbs_EDGE) {
570 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aSx));
571 if (BRep_Tool::Degenerated(aE)) {
572 TopExp_Explorer aExpE(aE, TopAbs_VERTEX);
573 TopoDS_Shape aSx1 = aExpE.Current();
575 if (myImages.IsBound(aSx1)) {
576 const BOPCol_ListOfShape& aLSIm=myImages.Find(aSx1);
581 bFlag=aMSV[iY].Contains(aSIm);
585 if (myOperation!=BOPAlgo_COMMON) {
597 //=======================================================================
598 //function : TypeToExplore
600 //=======================================================================
601 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
603 TopAbs_ShapeEnum aRet;
624 //=======================================================================
625 //function : BuildSolid
627 //=======================================================================
628 void BOPAlgo_BOP::BuildSolid()
630 Standard_Integer i, aNbF, aNbSx, iX, iErr;
631 TopAbs_Orientation aOr, aOr1;
635 TopExp_Explorer aExp;
636 BOPCol_IndexedMapOfShape aMFI;
637 BOPCol_IndexedDataMapOfShapeListOfShape aMFS, aMEF;
638 BOPCol_ListIteratorOfListOfShape aItLS;
639 BOPCol_ListOfShape aSFS;
640 BOPAlgo_BuilderSolid aSB;
644 aIt.Initialize(myRC);
645 for (; aIt.More(); aIt.Next()) {
646 const TopoDS_Shape& aSx=aIt.Value();
647 aExp.Init(aSx, TopAbs_FACE);
648 for (; aExp.More(); aExp.Next()) {
649 const TopoDS_Shape& aFx=aExp.Current();
651 aOr=aFx.Orientation();
652 if (aOr==TopAbs_INTERNAL) {
657 if (!aMFS.Contains(aFx)) {
658 BOPCol_ListOfShape aLSx;
664 iX=aMFS.FindIndex(aFx);
665 const TopoDS_Shape& aFx1=aMFS.FindKey(iX);
666 aOr1=aFx1.Orientation();
668 BOPCol_ListOfShape& aLSx=aMFS.ChangeFromKey(aFx);
676 BOPCol_ListOfShape aLF, aLFx; //faces that will be added in the end;
679 for (i=1; i<=aNbF; ++i) {
680 const TopoDS_Shape& aFx=aMFS.FindKey(i);
681 const BOPCol_ListOfShape& aLSx=aMFS(i);
684 BOPTools::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
685 if (IsBoundSplits(aFx, aMEF)){
693 aItLS.Initialize(aLF);
694 for(; aItLS.More(); aItLS.Next()) {
695 const TopoDS_Shape& aFx=aItLS.Value();
698 // add faces from aLFx to aSFS;
699 aItLS.Initialize(aLFx);
700 for (; aItLS.More(); aItLS.Next()) {
701 const TopoDS_Shape& aFx=aItLS.Value();
706 for (i=1; i<=aNbF; ++i) {
710 aFx.Orientation(TopAbs_FORWARD);
712 aFx.Orientation(TopAbs_REVERSED);
717 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
719 aSB.SetContext(myContext);
722 iErr=aSB.ErrorStatus();
724 myErrorStatus=30; // SolidBuilder failed
728 const BOPCol_ListOfShape& aLSR=aSB.Areas();
730 aItLS.Initialize(aLSR);
731 for (; aItLS.More(); aItLS.Next()) {
732 const TopoDS_Shape& aSR=aItLS.Value();
738 //=======================================================================
739 //function : IsBoundImages
741 //=======================================================================
742 Standard_Boolean BOPAlgo_BOP::IsBoundSplits(const TopoDS_Shape& aS,
743 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
745 Standard_Boolean bRet = Standard_False;
746 if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
750 BOPCol_ListIteratorOfListOfShape aIt;
751 Standard_Integer aNbLS;
752 TopAbs_Orientation anOr;
754 //check face aF may be connected to face from mySplits
755 TopExp_Explorer aExp(aS, TopAbs_EDGE);
756 for (; aExp.More(); aExp.Next()) {
757 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
759 anOr = aE.Orientation();
760 if (anOr==TopAbs_INTERNAL) {
764 if (BRep_Tool::Degenerated(aE)) {
768 const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
769 aNbLS = aLS.Extent();
775 for (; aIt.More(); aIt.Next()) {
776 const TopoDS_Shape& aSx = aIt.Value();
777 if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {