1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
20 #include <BOPAlgo_BOP.ixx>
22 #include <TopAbs_ShapeEnum.hxx>
24 #include <TopoDS_Compound.hxx>
25 #include <TopoDS_Iterator.hxx>
26 #include <BRep_Builder.hxx>
27 #include <TopExp_Explorer.hxx>
29 #include <BOPTools.hxx>
30 #include <BOPTools_AlgoTools.hxx>
31 #include <BOPTools_AlgoTools3D.hxx>
33 #include <BOPCol_ListOfShape.hxx>
34 #include <BOPAlgo_BuilderSolid.hxx>
35 #include <TopoDS_Edge.hxx>
38 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
40 //=======================================================================
43 //=======================================================================
44 BOPAlgo_BOP::BOPAlgo_BOP()
48 myMapTools(100, myAllocator)
53 //=======================================================================
56 //=======================================================================
57 BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator)
59 BOPAlgo_Builder(theAllocator),
61 myMapTools(100, myAllocator)
66 //=======================================================================
69 //=======================================================================
70 BOPAlgo_BOP::~BOPAlgo_BOP()
73 //=======================================================================
76 //=======================================================================
77 void BOPAlgo_BOP::Clear()
79 myOperation=BOPAlgo_UNKNOWN;
85 BOPAlgo_Builder::Clear();
87 //=======================================================================
88 //function : AddArgument
90 //=======================================================================
91 void BOPAlgo_BOP::AddArgument(const TopoDS_Shape& theShape)
93 if (myMapFence.Add(theShape)) {
94 myArguments.Append(theShape);
98 //=======================================================================
101 //=======================================================================
102 void BOPAlgo_BOP::AddTool(const TopoDS_Shape& theShape)
104 if (myMapTools.Add(theShape)) {
105 myTools.Append(theShape);
108 if (myMapFence.Add(theShape)) {
109 myArguments.Append(theShape);
113 //=======================================================================
116 //=======================================================================
117 const TopoDS_Shape& BOPAlgo_BOP::Object()const
121 //=======================================================================
124 //=======================================================================
125 const TopoDS_Shape& BOPAlgo_BOP::Tool()const
129 //=======================================================================
130 //function : SetOperation
132 //=======================================================================
133 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
135 myOperation=theOperation;
137 //=======================================================================
138 //function : Operation
140 //=======================================================================
141 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
145 //=======================================================================
146 //function : CheckData
148 //=======================================================================
149 void BOPAlgo_BOP::CheckData()
151 Standard_Integer i, aNb;
152 Standard_Boolean bFlag;
156 aNb=myArguments.Extent();
158 if (aNb!=1 || !(myArgs[0].IsSame(myArgs[1]))) {
159 myErrorStatus=10; // invalid number of arguments
169 myErrorStatus=myPaveFiller->ErrorStatus();
174 for (i=0; i<myNbArgs; ++i) {
175 if (myArgs[i].IsNull()) {
176 myErrorStatus=11; // argument is null shape
181 for (i=0; i<myNbArgs; ++i) {
182 bFlag = BOPTools_AlgoTools3D::IsEmptyShape(myArgs[i]);
188 for (i=0; i<myNbArgs; ++i) {
189 myDims[i]=BOPTools_AlgoTools::Dimension(myArgs[i]);
191 myErrorStatus=13; // non-homogenious argument
196 if (myOperation==BOPAlgo_UNKNOWN) {
197 myErrorStatus=14; // non-licit operation
200 else if (myDims[0]<myDims[1]) {
201 if (myOperation==BOPAlgo_FUSE ||
202 myOperation==BOPAlgo_CUT21) {
203 myErrorStatus=14; // non-licit operation for the arguments
207 else if (myDims[0]>myDims[1]) {
208 if (myOperation==BOPAlgo_FUSE ||
209 myOperation==BOPAlgo_CUT) {
210 myErrorStatus=14; // non-licit operation for the arguments
215 //=======================================================================
218 //=======================================================================
219 void BOPAlgo_BOP::Prepare()
224 BOPAlgo_Builder::Prepare();
226 if(myWarningStatus == 2) {
227 switch(myOperation) {
229 for ( i = 0; i < myNbArgs; i++ ) {
230 aBB.Add(myShape, myArgs[i]);
234 case BOPAlgo_SECTION:
237 if(BOPTools_AlgoTools3D::IsEmptyShape(myArgs[0])) {
240 aBB.Add(myShape, myArgs[0]);
244 if(BOPTools_AlgoTools3D::IsEmptyShape(myArgs[1])) {
247 aBB.Add(myShape, myArgs[1]);
255 //=======================================================================
256 //function : PerformInternal
258 //=======================================================================
259 void BOPAlgo_BOP::PerformInternal(const BOPAlgo_PaveFiller& theFiller)
264 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
265 myDS=myPaveFiller->PDS();
266 myContext=myPaveFiller->Context();
270 if (myErrorStatus && !myWarningStatus) {
279 if(myWarningStatus == 2) {
285 FillImagesVertices();
290 BuildResult(TopAbs_VERTEX);
300 BuildResult(TopAbs_EDGE);
304 //-------------------------------- SECTION f
305 if (myOperation==BOPAlgo_SECTION) {
311 //-------------------------------- SECTION t
314 FillImagesContainers(TopAbs_WIRE);
319 BuildResult(TopAbs_WIRE);
330 BuildResult(TopAbs_FACE);
336 FillImagesContainers(TopAbs_SHELL);
341 BuildResult(TopAbs_SHELL);
351 BuildResult(TopAbs_SOLID);
356 FillImagesContainers(TopAbs_COMPSOLID);
361 BuildResult(TopAbs_COMPSOLID);
366 FillImagesCompounds();
371 BuildResult(TopAbs_COMPOUND);
386 //=======================================================================
387 //function : BuildShape
389 //=======================================================================
390 void BOPAlgo_BOP::BuildShape()
392 Standard_Integer aDmin, aNbLCB;
393 TopAbs_ShapeEnum aT1, aT2, aTR;
394 TopoDS_Shape aR, aRC;
397 BOPCol_ListOfShape aLCB;
398 BOPCol_ListIteratorOfListOfShape aItLCB;
406 if (myDims[0]<myDims[1]) {
415 else if (aDmin==1 || aDmin==2) { //edges, faces
425 BOPTools_AlgoTools::MakeConnexityBlocks(myRC, aT1, aT2, aLCB);
426 aNbLCB=aLCB.Extent();
432 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
434 aItLCB.Initialize(aLCB);
435 for (; aItLCB.More(); aItLCB.Next()) {
436 BOPTools_AlgoTools::MakeContainer(aTR, aR);
438 const TopoDS_Shape& aCB=aItLCB.Value();
440 for (; aIt.More(); aIt.Next()) {
441 const TopoDS_Shape& aS=aIt.Value();
445 if (aTR==TopAbs_SHELL) {
446 BOPTools_AlgoTools::OrientFacesOnShell(aR);
452 }// elase if (aDmin==1 || aDmin==2) {
455 if (myOperation==BOPAlgo_FUSE) {
463 //=======================================================================
466 //=======================================================================
467 void BOPAlgo_BOP::BuildRC()
469 Standard_Boolean bFlag;
470 Standard_Integer i, aDmin, aNb[2], iX, iY;
471 TopAbs_ShapeEnum aTmin;
472 TopoDS_Compound aC, aCS[2];
474 TopExp_Explorer aExp;
475 BOPCol_ListIteratorOfListOfShape aItIm;
476 BOPCol_IndexedMapOfShape aMS[2];
477 BOPCol_IndexedMapOfShape aMSV[2];
482 if (myOperation==BOPAlgo_FUSE) {
483 aBB.MakeCompound(aC);
484 aTmin=TypeToExplore(myDims[0]);
485 aExp.Init(myShape, aTmin);
486 for (; aExp.More(); aExp.Next()) {
487 const TopoDS_Shape& aS=aExp.Current();
496 // 1. Compounds CS that consist of an Arg or Images of the Arg
497 for (i=0; i<myNbArgs; ++i) {
498 aBB.MakeCompound(aCS[i]);
499 const TopoDS_Shape& aS=myArgs[i];
500 if (myImages.IsBound(aS)){
501 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
502 aItIm.Initialize(aLSIm);
503 for (; aItIm.More(); aItIm.Next()) {
504 const TopoDS_Shape& aSIm=aItIm.Value();
505 aBB.Add(aCS[i], aSIm);
514 if (myDims[0]<myDims[1]) {
517 aTmin=TypeToExplore(aDmin);
518 for (i=0; i<myNbArgs; ++i) {
519 aExp.Init(aCS[i], aTmin);
520 for (; aExp.More(); aExp.Next()) {
521 const TopoDS_Shape aS=aExp.Current();
522 if (aTmin == TopAbs_EDGE) {
523 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aS));
524 if (BRep_Tool::Degenerated(aE)) {
525 TopExp_Explorer aExpE(aE, TopAbs_VERTEX);
526 TopoDS_Shape aS1 = aExpE.Current();
527 if (myImages.IsBound(aS1)){
528 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS1);
529 const TopoDS_Shape& aSIm=aLSIm.First();
537 if (myImages.IsBound(aS)){
538 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
539 aItIm.Initialize(aLSIm);
540 for (; aItIm.More(); aItIm.Next()) {
541 const TopoDS_Shape& aSIm=aItIm.Value();
549 aNb[i]=aMS[i].Extent();
552 aBB.MakeCompound(aC);
554 // 3. Find common parts
555 if (myOperation==BOPAlgo_COMMON) {
556 if (myDims[0]==myDims[1]) {
557 iX=(aNb[0]>aNb[1])? 1 : 0;
559 iX=(myDims[0]<myDims[1]) ? 0 : 1;
563 else if (myOperation==BOPAlgo_CUT) {
567 else if (myOperation==BOPAlgo_CUT21) {
571 for (i=1; i<=aNb[iX]; ++i) {
572 const TopoDS_Shape& aSx=aMS[iX].FindKey(i);
573 bFlag=aMS[iY].Contains(aSx);
574 if (aTmin == TopAbs_EDGE) {
575 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aSx));
576 if (BRep_Tool::Degenerated(aE)) {
577 TopExp_Explorer aExpE(aE, TopAbs_VERTEX);
578 TopoDS_Shape aSx1 = aExpE.Current();
580 if (myImages.IsBound(aSx1)) {
581 const BOPCol_ListOfShape& aLSIm=myImages.Find(aSx1);
586 bFlag=aMSV[iY].Contains(aSIm);
590 if (myOperation!=BOPAlgo_COMMON) {
602 //=======================================================================
603 //function : TypeToExplore
605 //=======================================================================
606 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
608 TopAbs_ShapeEnum aRet;
629 //=======================================================================
630 //function : BuildSolid
632 //=======================================================================
633 void BOPAlgo_BOP::BuildSolid()
635 Standard_Integer i, aNbF, aNbSx, iX, iErr;
636 TopAbs_Orientation aOr, aOr1;
640 TopExp_Explorer aExp;
641 BOPCol_IndexedMapOfShape aMFI;
642 BOPCol_IndexedDataMapOfShapeListOfShape aMFS, aMEF;
643 BOPCol_ListIteratorOfListOfShape aItLS;
644 BOPCol_ListOfShape aSFS;
645 BOPAlgo_BuilderSolid aSB;
649 aIt.Initialize(myRC);
650 for (; aIt.More(); aIt.Next()) {
651 const TopoDS_Shape& aSx=aIt.Value();
652 aExp.Init(aSx, TopAbs_FACE);
653 for (; aExp.More(); aExp.Next()) {
654 const TopoDS_Shape& aFx=aExp.Current();
656 aOr=aFx.Orientation();
657 if (aOr==TopAbs_INTERNAL) {
662 if (!aMFS.Contains(aFx)) {
663 BOPCol_ListOfShape aLSx;
669 iX=aMFS.FindIndex(aFx);
670 const TopoDS_Shape& aFx1=aMFS.FindKey(iX);
671 aOr1=aFx1.Orientation();
673 BOPCol_ListOfShape& aLSx=aMFS.ChangeFromKey(aFx);
681 BOPCol_ListOfShape aLF, aLFx; //faces that will be added in the end;
684 for (i=1; i<=aNbF; ++i) {
685 const TopoDS_Shape& aFx=aMFS.FindKey(i);
686 const BOPCol_ListOfShape& aLSx=aMFS(i);
689 BOPTools::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
690 if (IsBoundSplits(aFx, aMEF)){
698 aItLS.Initialize(aLF);
699 for(; aItLS.More(); aItLS.Next()) {
700 const TopoDS_Shape& aFx=aItLS.Value();
703 // add faces from aLFx to aSFS;
704 aItLS.Initialize(aLFx);
705 for (; aItLS.More(); aItLS.Next()) {
706 const TopoDS_Shape& aFx=aItLS.Value();
711 for (i=1; i<=aNbF; ++i) {
715 aFx.Orientation(TopAbs_FORWARD);
717 aFx.Orientation(TopAbs_REVERSED);
722 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
724 aSB.SetContext(myContext);
727 iErr=aSB.ErrorStatus();
729 myErrorStatus=30; // SolidBuilder failed
733 const BOPCol_ListOfShape& aLSR=aSB.Areas();
735 aItLS.Initialize(aLSR);
736 for (; aItLS.More(); aItLS.Next()) {
737 const TopoDS_Shape& aSR=aItLS.Value();
743 //=======================================================================
744 //function : IsBoundImages
746 //=======================================================================
747 Standard_Boolean BOPAlgo_BOP::IsBoundSplits(const TopoDS_Shape& aS,
748 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
750 Standard_Boolean bRet = Standard_False;
751 if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
755 BOPCol_ListIteratorOfListOfShape aIt;
756 Standard_Integer aNbLS;
757 TopAbs_Orientation anOr;
759 //check face aF may be connected to face from mySplits
760 TopExp_Explorer aExp(aS, TopAbs_EDGE);
761 for (; aExp.More(); aExp.Next()) {
762 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
764 anOr = aE.Orientation();
765 if (anOr==TopAbs_INTERNAL) {
769 if (BRep_Tool::Degenerated(aE)) {
773 const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
774 aNbLS = aLS.Extent();
780 for (; aIt.More(); aIt.Next()) {
781 const TopoDS_Shape& aSx = aIt.Value();
782 if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {