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 under
7 // the terms of the GNU Lesser General Public License 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 <TopoDS_Edge.hxx>
22 #include <BRep_Builder.hxx>
23 #include <TopExp_Explorer.hxx>
25 #include <BOPCol_ListOfShape.hxx>
26 #include <BOPCol_MapOfShape.hxx>
27 #include <BOPCol_IndexedMapOfShape.hxx>
28 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
29 #include <BOPCol_DataMapOfShapeShape.hxx>
31 #include <BOPDS_DS.hxx>
33 #include <BOPTools.hxx>
34 #include <BOPTools_AlgoTools.hxx>
35 #include <BOPTools_AlgoTools3D.hxx>
36 #include <BOPTools_AlgoTools.hxx>
38 #include <BOPAlgo_BuilderSolid.hxx>
40 #include <BRep_Tool.hxx>
41 #include <NCollection_IncAllocator.hxx>
44 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
47 //=======================================================================
50 //=======================================================================
51 BOPAlgo_BOP::BOPAlgo_BOP()
55 myMapTools(100, myAllocator)
59 //=======================================================================
62 //=======================================================================
63 BOPAlgo_BOP::BOPAlgo_BOP
64 (const Handle(NCollection_BaseAllocator)& theAllocator)
66 BOPAlgo_Builder(theAllocator),
68 myMapTools(100, myAllocator)
72 //=======================================================================
75 //=======================================================================
76 BOPAlgo_BOP::~BOPAlgo_BOP()
79 //=======================================================================
82 //=======================================================================
83 void BOPAlgo_BOP::Clear()
85 myOperation=BOPAlgo_UNKNOWN;
91 BOPAlgo_Builder::Clear();
93 //=======================================================================
94 //function : SetOperation
96 //=======================================================================
97 void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
99 myOperation=theOperation;
101 //=======================================================================
102 //function : Operation
104 //=======================================================================
105 BOPAlgo_Operation BOPAlgo_BOP::Operation()const
109 //=======================================================================
112 //=======================================================================
113 void BOPAlgo_BOP::AddTool(const TopoDS_Shape& theShape)
115 if (myMapTools.Add(theShape)) {
116 myTools.Append(theShape);
119 //=======================================================================
120 //function : CheckData
122 //=======================================================================
123 void BOPAlgo_BOP::CheckData()
125 Standard_Integer i, j, iDim, aNbArgs, aNbTools;
126 Standard_Boolean bFlag;
127 BOPCol_ListIteratorOfListOfShape aItLS;
131 aNbArgs=myArguments.Extent();
133 myErrorStatus=100; // invalid number of Arguments
137 aNbTools=myTools.Extent();
139 myErrorStatus=100; // invalid number of Tools
148 myErrorStatus=myPaveFiller->ErrorStatus();
153 for (i=0; i<2; ++i) {
154 const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
155 aItLS.Initialize(aLS);
156 for (j=0; aItLS.More(); aItLS.Next(), ++j) {
157 const TopoDS_Shape& aS=aItLS.Value();
158 bFlag=BOPTools_AlgoTools3D::IsEmptyShape(aS);
163 iDim=BOPTools_AlgoTools::Dimension(aS);
165 myErrorStatus=13; // non-homogenious argument
174 if (iDim!=myDims[i]) {
175 myErrorStatus=13; // non-homogenious argument
181 if (myOperation==BOPAlgo_UNKNOWN) {
182 myErrorStatus=14; // non-licit operation
185 else if (myDims[0]<myDims[1]) {
186 if (myOperation==BOPAlgo_FUSE ||
187 myOperation==BOPAlgo_CUT21) {
188 myErrorStatus=14; // non-licit operation for the arguments
192 else if (myDims[0]>myDims[1]) {
193 if (myOperation==BOPAlgo_FUSE ||
194 myOperation==BOPAlgo_CUT) {
195 myErrorStatus=14; // non-licit operation for the arguments
200 //=======================================================================
203 //=======================================================================
204 void BOPAlgo_BOP::Prepare()
207 BOPAlgo_Builder::Prepare();
209 if(myWarningStatus == 2) {
212 BOPCol_ListIteratorOfListOfShape aItLS;
214 switch(myOperation) {
216 for (i=0; i<2; ++i) {
217 const BOPCol_ListOfShape& aLS=(!i)? myArguments : myTools;
218 aItLS.Initialize(aLS);
219 for (; aItLS.More(); aItLS.Next()) {
220 const TopoDS_Shape& aS=aItLS.Value();
221 aBB.Add(myShape, aS);
228 aItLS.Initialize(myArguments);
229 for (; aItLS.More(); aItLS.Next()) {
230 const TopoDS_Shape& aS=aItLS.Value();
231 if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
232 aBB.Add(myShape, aS);
238 case BOPAlgo_CUT21: {
239 aItLS.Initialize(myTools);
240 for (; aItLS.More(); aItLS.Next()) {
241 const TopoDS_Shape& aS=aItLS.Value();
242 if(!BOPTools_AlgoTools3D::IsEmptyShape(aS)) {
243 aBB.Add(myShape, aS);
250 case BOPAlgo_SECTION:
256 //=======================================================================
257 //function : BuildResult
259 //=======================================================================
260 void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
262 TopAbs_ShapeEnum aType;
264 BOPCol_MapOfShape aM;
265 BOPCol_ListIteratorOfListOfShape aIt, aItIm;
269 const BOPCol_ListOfShape& aLA=myDS->Arguments();
271 for (; aIt.More(); aIt.Next()) {
272 const TopoDS_Shape& aS=aIt.Value();
273 aType=aS.ShapeType();
274 if (aType==theType) {
275 if (myImages.IsBound(aS)){
276 const BOPCol_ListOfShape& aLSIm=myImages.Find(aS);
277 aItIm.Initialize(aLSIm);
278 for (; aItIm.More(); aItIm.Next()) {
279 const TopoDS_Shape& aSIm=aItIm.Value();
281 aBB.Add(myShape, aSIm);
287 aBB.Add(myShape, aS);
293 //=======================================================================
296 //=======================================================================
297 void BOPAlgo_BOP::Perform()
299 Handle(NCollection_BaseAllocator) aAllocator;
300 BOPAlgo_PaveFiller* pPF;
301 BOPCol_ListIteratorOfListOfShape aItLS;
305 if (myEntryPoint==1) {
312 aAllocator=new NCollection_IncAllocator;
313 BOPCol_ListOfShape aLS(aAllocator);
315 aItLS.Initialize(myArguments);
316 for (; aItLS.More(); aItLS.Next()) {
317 const TopoDS_Shape& aS=aItLS.Value();
321 aItLS.Initialize(myTools);
322 for (; aItLS.More(); aItLS.Next()) {
323 const TopoDS_Shape& aS=aItLS.Value();
327 pPF=new BOPAlgo_PaveFiller(aAllocator);
328 pPF->SetArguments(aLS);
333 PerformInternal(*pPF);
335 //=======================================================================
336 //function : PerformInternal1
338 //=======================================================================
339 void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
344 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
345 myDS=myPaveFiller->PDS();
346 myContext=myPaveFiller->Context();
350 if (myErrorStatus && !myWarningStatus) {
360 if(myWarningStatus == 2) {
365 FillImagesVertices();
370 BuildResult(TopAbs_VERTEX);
380 BuildResult(TopAbs_EDGE);
384 //-------------------------------- SECTION
385 if (myOperation==BOPAlgo_SECTION) {
391 //--------------------------------
394 FillImagesContainers(TopAbs_WIRE);
399 BuildResult(TopAbs_WIRE);
410 BuildResult(TopAbs_FACE);
416 FillImagesContainers(TopAbs_SHELL);
421 BuildResult(TopAbs_SHELL);
431 BuildResult(TopAbs_SOLID);
436 FillImagesContainers(TopAbs_COMPSOLID);
441 BuildResult(TopAbs_COMPSOLID);
446 FillImagesCompounds();
451 BuildResult(TopAbs_COMPOUND);
468 //=======================================================================
471 //=======================================================================
472 void BOPAlgo_BOP::BuildRC()
474 Standard_Boolean bFlag1, bFlag2, bIsBound;
475 Standard_Integer aDmin;
476 TopAbs_ShapeEnum aTmin;
478 TopoDS_Shape aSAIm, aSTIm;
480 TopExp_Explorer aExp;
481 BOPCol_DataMapOfShapeShape aDMSSA;
482 BOPCol_ListIteratorOfListOfShape aItLS, aItIm;
486 aBB.MakeCompound(aC);
489 if (myOperation==BOPAlgo_FUSE) {
490 aTmin=TypeToExplore(myDims[0]);
491 aExp.Init(myShape, aTmin);
492 for (; aExp.More(); aExp.Next()) {
493 const TopoDS_Shape& aS=aExp.Current();
501 if (myDims[0] < myDims[1]) {
504 aTmin=TypeToExplore(aDmin);
506 // B. Common, Cut, Cut21
508 bFlag1=(myOperation==BOPAlgo_COMMON || myOperation==BOPAlgo_CUT21);
509 bFlag2=(myOperation==BOPAlgo_CUT || myOperation==BOPAlgo_CUT21);
511 const BOPCol_ListOfShape& aLA=( bFlag1) ? myArguments : myTools;
512 aItLS.Initialize(aLA);
513 for (; aItLS.More(); aItLS.Next()) {
514 const TopoDS_Shape& aSA=aItLS.Value();
516 if (myImages.IsBound(aSA)){
517 const BOPCol_ListOfShape& aLSAIm=myImages.Find(aSA);
518 aItIm.Initialize(aLSAIm);
519 for (; aItIm.More(); aItIm.Next()) {
520 const TopoDS_Shape& aSAIm=aItIm.Value();
521 aExp.Init(aSAIm, aTmin);
522 for (; aExp.More(); aExp.Next()) {
523 const TopoDS_Shape aSIm=aExp.Current();
524 aDMSSA.Bind(aSIm, aSIm);
530 aExp.Init(aSA, aTmin);
531 for (; aExp.More(); aExp.Next()) {
532 const TopoDS_Shape aSIm=aExp.Current();
533 aDMSSA.Bind(aSIm, aSIm);
536 } //for (; aItLS.More(); aItLS.Next())
538 const BOPCol_ListOfShape& aLT=(!bFlag1) ? myArguments : myTools;
539 aItLS.Initialize(aLT);
540 for (; aItLS.More(); aItLS.Next()) {
541 const TopoDS_Shape& aST=aItLS.Value();
542 if (myImages.IsBound(aST)){
543 const BOPCol_ListOfShape& aLSTIm=myImages.Find(aST);
544 aItIm.Initialize(aLSTIm);
545 for (; aItIm.More(); aItIm.Next()) {
546 const TopoDS_Shape& aSTIm=aItIm.Value();
547 aExp.Init(aSTIm, aTmin);
548 for (; aExp.More(); aExp.Next()) {
549 const TopoDS_Shape aSIm=aExp.Current();
550 // skip degenerated edges
551 if (aTmin==TopAbs_EDGE) {
552 const TopoDS_Edge& aEIm=*((TopoDS_Edge*)&aSIm);
553 if (BRep_Tool::Degenerated(aEIm)) {
558 bIsBound=aDMSSA.IsBound(aSIm);
559 if (!bFlag2) { // ie common
561 const TopoDS_Shape& aSImA=aDMSSA.Find(aSIm);
565 else {// ie cut or cut21
574 aExp.Init(aST, aTmin);
575 for (; aExp.More(); aExp.Next()) {
576 const TopoDS_Shape aSIm=aExp.Current();
577 // skip degenerated edges
578 if (aTmin==TopAbs_EDGE) {
579 const TopoDS_Edge& aEIm=*((TopoDS_Edge*)&aSIm);
580 if (BRep_Tool::Degenerated(aEIm)) {
584 bIsBound=aDMSSA.IsBound(aSIm);
585 if (!bFlag2) { // ie common
587 const TopoDS_Shape& aSImA=aDMSSA.Find(aSIm);
591 else {// ie cut or cut21
598 } //for (; aItLS.More(); aItLS.Next())
600 // the squats around degeneracy
601 if (aTmin!=TopAbs_EDGE) {
605 //---------------------------------------------------------
607 // The squats around degenerated edges
608 Standard_Integer i, aNbS, nVD;
609 TopAbs_ShapeEnum aType;
610 BOPCol_IndexedMapOfShape aMVC;
613 BOPTools::MapShapes(aC, TopAbs_VERTEX, aMVC);
616 aNbS=myDS->NbSourceShapes();
617 for (i=0; i<aNbS; ++i) {
618 const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
619 aType=aSI.ShapeType();
624 const TopoDS_Edge& aE=*((TopoDS_Edge*)&aSI.Shape());
625 if (!BRep_Tool::Degenerated(aE)) {
629 nVD=aSI.SubShapes().First();
630 const TopoDS_Shape& aVD=myDS->Shape(nVD);
632 if (!aMVC.Contains(aVD)) {
636 if (myDS->IsNewShape(nVD)) {
640 if (myDS->HasInterf(nVD)) {
649 //=======================================================================
650 //function : BuildShape
652 //=======================================================================
653 void BOPAlgo_BOP::BuildShape()
655 Standard_Integer aDmin, aNbLCB;
656 TopAbs_ShapeEnum aT1, aT2, aTR;
657 TopoDS_Shape aR, aRC;
660 BOPCol_ListOfShape aLCB;
661 BOPCol_ListIteratorOfListOfShape aItLCB;
668 if (myDims[0]<myDims[1]) {
677 else if (aDmin==1 || aDmin==2) { //edges, faces
687 BOPTools_AlgoTools::MakeConnexityBlocks
688 (myRC, aT1, aT2, aLCB);
689 aNbLCB=aLCB.Extent();
695 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
697 aItLCB.Initialize(aLCB);
698 for (; aItLCB.More(); aItLCB.Next()) {
699 BOPTools_AlgoTools::MakeContainer(aTR, aR);
701 const TopoDS_Shape& aCB=aItLCB.Value();
703 for (; aIt.More(); aIt.Next()) {
704 const TopoDS_Shape& aS=aIt.Value();
708 if (aTR==TopAbs_SHELL) {
709 BOPTools_AlgoTools::OrientFacesOnShell(aR);
715 }// elase if (aDmin==1 || aDmin==2) {
718 Standard_Integer aNbObjs, aNbTools;
720 aNbObjs=myArguments.Extent();
721 aNbTools=myTools.Extent();
723 if (aNbObjs==1 && aNbTools==1) {
724 if (myOperation==BOPAlgo_FUSE) {
736 //=======================================================================
737 //function : BuildSolid
739 //=======================================================================
740 void BOPAlgo_BOP::BuildSolid()
742 Standard_Integer i, aNbF, aNbSx, iX, iErr;
743 TopAbs_Orientation aOr, aOr1;
747 TopExp_Explorer aExp;
748 BOPCol_IndexedMapOfShape aMFI;
749 BOPCol_IndexedDataMapOfShapeListOfShape aMFS, aMEF;
750 BOPCol_ListIteratorOfListOfShape aItLS;
751 BOPCol_ListOfShape aSFS;
752 BOPAlgo_BuilderSolid aSB;
756 aIt.Initialize(myRC);
757 for (; aIt.More(); aIt.Next()) {
758 const TopoDS_Shape& aSx=aIt.Value();
759 aExp.Init(aSx, TopAbs_FACE);
760 for (; aExp.More(); aExp.Next()) {
761 const TopoDS_Shape& aFx=aExp.Current();
763 aOr=aFx.Orientation();
764 if (aOr==TopAbs_INTERNAL) {
769 if (!aMFS.Contains(aFx)) {
770 BOPCol_ListOfShape aLSx;
776 iX=aMFS.FindIndex(aFx);
777 const TopoDS_Shape& aFx1=aMFS.FindKey(iX);
778 aOr1=aFx1.Orientation();
780 BOPCol_ListOfShape& aLSx=aMFS.ChangeFromKey(aFx);
787 //faces that will be added in the end;
788 BOPCol_ListOfShape aLF, aLFx;
791 for (i=1; i<=aNbF; ++i) {
792 const TopoDS_Shape& aFx=aMFS.FindKey(i);
793 const BOPCol_ListOfShape& aLSx=aMFS(i);
796 BOPTools::MapShapesAndAncestors
797 (aFx,TopAbs_EDGE, TopAbs_FACE, aMEF);
798 if (IsBoundSplits(aFx, aMEF)){
806 aItLS.Initialize(aLF);
807 for(; aItLS.More(); aItLS.Next()) {
808 const TopoDS_Shape& aFx=aItLS.Value();
811 // add faces from aLFx to aSFS;
812 aItLS.Initialize(aLFx);
813 for (; aItLS.More(); aItLS.Next()) {
814 const TopoDS_Shape& aFx=aItLS.Value();
819 for (i=1; i<=aNbF; ++i) {
823 aFx.Orientation(TopAbs_FORWARD);
825 aFx.Orientation(TopAbs_REVERSED);
830 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
832 aSB.SetContext(myContext);
835 iErr=aSB.ErrorStatus();
837 myErrorStatus=30; // SolidBuilder failed
841 const BOPCol_ListOfShape& aLSR=aSB.Areas();
843 aItLS.Initialize(aLSR);
844 for (; aItLS.More(); aItLS.Next()) {
845 const TopoDS_Shape& aSR=aItLS.Value();
850 //=======================================================================
851 //function : IsBoundImages
853 //=======================================================================
854 Standard_Boolean BOPAlgo_BOP::IsBoundSplits
855 (const TopoDS_Shape& aS,
856 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
858 Standard_Boolean bRet = Standard_False;
859 if (mySplits.IsBound(aS) || myOrigins.IsBound(aS)) {
863 BOPCol_ListIteratorOfListOfShape aIt;
864 Standard_Integer aNbLS;
865 TopAbs_Orientation anOr;
867 //check face aF may be connected to face from mySplits
868 TopExp_Explorer aExp(aS, TopAbs_EDGE);
869 for (; aExp.More(); aExp.Next()) {
870 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
872 anOr = aE.Orientation();
873 if (anOr==TopAbs_INTERNAL) {
877 if (BRep_Tool::Degenerated(aE)) {
881 const BOPCol_ListOfShape& aLS=aMEF.FindFromKey(aE);
882 aNbLS = aLS.Extent();
888 for (; aIt.More(); aIt.Next()) {
889 const TopoDS_Shape& aSx = aIt.Value();
890 if (mySplits.IsBound(aSx) || myOrigins.IsBound(aS)) {
898 //=======================================================================
899 //function : TypeToExplore
901 //=======================================================================
902 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
904 TopAbs_ShapeEnum aRet;