1 // Created on: 2000-03-16
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <BOPTest.ixx>
20 #include <TCollection_AsciiString.hxx>
23 #include <DrawTrSurf.hxx>
24 #include <Draw_Color.hxx>
27 #include <NCollection_BaseAllocator.hxx>
28 #include <NCollection_IncAllocator.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <TopoDS_Iterator.hxx>
34 #include <BRep_Builder.hxx>
36 #include <IntTools_FaceFace.hxx>
37 #include <IntTools_Curve.hxx>
39 #include <BOPCol_ListOfShape.hxx>
41 #include <BOPDS_DS.hxx>
43 #include <BOPAlgo_PaveFiller.hxx>
44 #include <BOPAlgo_Operation.hxx>
45 #include <BOPAlgo_BOP.hxx>
46 #include <BOPAlgo_MakerVolume.hxx>
47 #include <BOPAlgo_Section.hxx>
49 #include <BRepAlgoAPI_BooleanOperation.hxx>
50 #include <BRepAlgoAPI_Common.hxx>
51 #include <BRepAlgoAPI_Fuse.hxx>
52 #include <BRepAlgoAPI_Cut.hxx>
53 #include <BRepAlgoAPI_Section.hxx>
55 #include <BOPTest_DrawableShape.hxx>
56 #include <BOPTest_Objects.hxx>
59 static BOPAlgo_PaveFiller* pPF=NULL;
63 Standard_Integer bopsmt(Draw_Interpretor& di,
66 const BOPAlgo_Operation aOp);
68 Standard_Integer bsmt (Draw_Interpretor& di,
71 const BOPAlgo_Operation aOp);
73 static Standard_Integer bop (Draw_Interpretor&, Standard_Integer, const char**);
74 static Standard_Integer bopsection(Draw_Interpretor&, Standard_Integer, const char**);
75 static Standard_Integer boptuc (Draw_Interpretor&, Standard_Integer, const char**);
76 static Standard_Integer bopcut (Draw_Interpretor&, Standard_Integer, const char**);
77 static Standard_Integer bopfuse (Draw_Interpretor&, Standard_Integer, const char**);
78 static Standard_Integer bopcommon (Draw_Interpretor&, Standard_Integer, const char**);
80 static Standard_Integer bsection (Draw_Interpretor&, Standard_Integer, const char**);
81 static Standard_Integer btuc (Draw_Interpretor&, Standard_Integer, const char**);
82 static Standard_Integer bcut (Draw_Interpretor&, Standard_Integer, const char**);
83 static Standard_Integer bfuse (Draw_Interpretor&, Standard_Integer, const char**);
84 static Standard_Integer bcommon (Draw_Interpretor&, Standard_Integer, const char**);
86 static Standard_Integer bopcurves (Draw_Interpretor&, Standard_Integer, const char**);
87 static Standard_Integer bopnews (Draw_Interpretor&, Standard_Integer, const char**);
89 static Standard_Integer bparallelmode(Draw_Interpretor&, Standard_Integer, const char**);
91 static Standard_Integer mkvolume (Draw_Interpretor&, Standard_Integer, const char**);
93 //=======================================================================
94 //function : BOPCommands
96 //=======================================================================
97 void BOPTest::BOPCommands(Draw_Interpretor& theCommands)
99 static Standard_Boolean done = Standard_False;
101 done = Standard_True;
103 const char* g = "BOP commands";
106 theCommands.Add("bop" , "use bop s1 s2 [tol]" , __FILE__, bop, g);
107 theCommands.Add("bopcommon" , "use bopcommon r" , __FILE__, bopcommon, g);
108 theCommands.Add("bopfuse" , "use bopfuse r" , __FILE__,bopfuse, g);
109 theCommands.Add("bopcut" , "use bopcut r" , __FILE__,bopcut, g);
110 theCommands.Add("boptuc" , "use boptuc r" , __FILE__,boptuc, g);
111 theCommands.Add("bopsection", "use bopsection r" , __FILE__,bopsection, g);
113 theCommands.Add("bcommon" , "use bcommon r s1 s2 [tol]" , __FILE__,bcommon, g);
114 theCommands.Add("bfuse" , "use bfuse r s1 s2 [tol]" , __FILE__,bfuse, g);
115 theCommands.Add("bcut" , "use bcut r s1 s2 [tol]" , __FILE__,bcut, g);
116 theCommands.Add("btuc" , "use btuc r s1 s2 [tol]" , __FILE__,btuc, g);
117 theCommands.Add("bsection", "Use >bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na] [tol]",
118 __FILE__, bsection, g);
120 theCommands.Add("bopcurves", "use bopcurves F1 F2 [-2d]", __FILE__, bopcurves, g);
121 theCommands.Add("bopnews", "use bopnews -v[e,f]" , __FILE__, bopnews, g);
122 theCommands.Add("bparallelmode", "bparallelmode [1/0] : show / set parallel mode for boolean operations",
123 __FILE__, bparallelmode, g);
124 theCommands.Add("mkvolume", "make solids from set of shapes.\nmkvolume r b1 b2 ... [-c] [-ni] [-s] [tol]",
125 __FILE__, mkvolume , g);
128 //=======================================================================
131 //=======================================================================
132 Standard_Integer bop(Draw_Interpretor& di, Standard_Integer n, const char** a)
135 Standard_Boolean bRunParallel;
136 Standard_Integer iErr;
138 TopoDS_Shape aS1, aS2;
139 BOPCol_ListOfShape aLC;
141 if (n < 3 || n > 4) {
142 di << " use bop Shape1 Shape2 [tol]\n";
146 aS1=DBRep::Get(a[1]);
147 aS2=DBRep::Get(a[2]);
149 if (aS1.IsNull() || aS2.IsNull()) {
150 di << " null shapes are not allowed \n";
154 aTol=BOPTest_Objects::FuzzyValue();
156 aTol = Draw::Atof(a[3]);
159 bRunParallel=BOPTest_Objects::RunParallel();
168 Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
169 pPF=new BOPAlgo_PaveFiller(aAL);
171 pPF->SetArguments(aLC);
172 pPF->SetFuzzyValue(aTol);
173 pPF->SetRunParallel(bRunParallel);
176 iErr=pPF->ErrorStatus();
178 Sprintf(buf, " ErrorStatus : %d\n", iErr);
185 //=======================================================================
186 //function : bopcommon
188 //=======================================================================
189 Standard_Integer bopcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
191 return bopsmt(di, n, a, BOPAlgo_COMMON);
193 //=======================================================================
196 //=======================================================================
197 Standard_Integer bopfuse(Draw_Interpretor& di, Standard_Integer n, const char** a)
199 return bopsmt(di, n, a, BOPAlgo_FUSE);
201 //=======================================================================
204 //=======================================================================
205 Standard_Integer bopcut(Draw_Interpretor& di, Standard_Integer n, const char** a)
207 return bopsmt(di, n, a, BOPAlgo_CUT);
209 //=======================================================================
212 //=======================================================================
213 Standard_Integer boptuc(Draw_Interpretor& di, Standard_Integer n, const char** a)
215 return bopsmt(di, n, a, BOPAlgo_CUT21);
217 //=======================================================================
220 //=======================================================================
221 Standard_Integer bopsmt(Draw_Interpretor& di,
224 const BOPAlgo_Operation aOp)
227 di << " use bopsmt r\n [tol]";
232 di << " prepare PaveFiller first\n";
236 if (pPF->ErrorStatus()) {
237 di << " PaveFiller has not been done\n";
242 Standard_Boolean bRunParallel;
243 Standard_Integer aNb, iErr;
246 const BOPCol_ListOfShape& aLC=pPF->Arguments();
249 Sprintf (buf, " wrong number of arguments %s\n", aNb);
254 bRunParallel=BOPTest_Objects::RunParallel();
256 const TopoDS_Shape& aS1=aLC.First();
257 const TopoDS_Shape& aS2=aLC.Last();
259 aBOP.AddArgument(aS1);
261 aBOP.SetOperation(aOp);
262 aBOP.SetRunParallel (bRunParallel);
264 aBOP.PerformWithFiller(*pPF);
265 iErr=aBOP.ErrorStatus();
267 Sprintf(buf, " ErrorStatus : %d\n", iErr);
272 const TopoDS_Shape& aR=aBOP.Shape();
274 di << " null shape\n";
278 DBRep::Set(a[1], aR);
281 //=======================================================================
282 //function : bopsection
284 //=======================================================================
285 Standard_Integer bopsection(Draw_Interpretor& di, Standard_Integer n, const char** a)
288 di << " use bopsmt r\n";
293 di << " prepare PaveFiller first\n";
297 if (pPF->ErrorStatus()) {
298 di << " PaveFiller has not been done\n";
303 Standard_Boolean bRunParallel;
304 Standard_Integer aNb, iErr;
305 BOPAlgo_Section aBOP;
307 const BOPCol_ListOfShape& aLC=pPF->Arguments();
310 Sprintf (buf, " wrong number of arguments %s\n", aNb);
315 bRunParallel=BOPTest_Objects::RunParallel();
317 const TopoDS_Shape& aS1=aLC.First();
318 const TopoDS_Shape& aS2=aLC.Last();
320 aBOP.AddArgument(aS1);
321 aBOP.AddArgument(aS2);
322 aBOP.SetRunParallel (bRunParallel);
324 aBOP.PerformWithFiller(*pPF);
325 iErr=aBOP.ErrorStatus();
327 Sprintf(buf, " ErrorStatus : %d\n", iErr);
332 const TopoDS_Shape& aR=aBOP.Shape();
334 di << " null shape\n";
338 DBRep::Set(a[1], aR);
341 //=======================================================================
344 //=======================================================================
345 Standard_Integer bcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
347 return bsmt(di, n, a, BOPAlgo_COMMON);
349 //=======================================================================
352 //=======================================================================
353 Standard_Integer bfuse (Draw_Interpretor& di, Standard_Integer n, const char** a)
355 return bsmt(di, n, a, BOPAlgo_FUSE);
357 //=======================================================================
360 //=======================================================================
361 Standard_Integer bcut (Draw_Interpretor& di, Standard_Integer n, const char** a)
363 return bsmt(di, n, a, BOPAlgo_CUT);
365 //=======================================================================
368 //=======================================================================
369 Standard_Integer btuc (Draw_Interpretor& di, Standard_Integer n, const char** a)
371 return bsmt(di, n, a, BOPAlgo_CUT21);
373 //=======================================================================
374 //function : bsection
376 //=======================================================================
377 Standard_Integer bsection(Draw_Interpretor& di,
381 const char* usage = " Usage: bsection Result s1 s2 [-n2d/-n2d1/-n2d2] [-na] [tol]\n";
387 TopoDS_Shape aS1 = DBRep::Get(a[2]);
388 TopoDS_Shape aS2 = DBRep::Get(a[3]);
390 if (aS1.IsNull() || aS2.IsNull()) {
391 di << " Null shapes are not allowed \n";
396 Standard_Boolean bRunParallel, bApp, bPC1, bPC2;
397 Standard_Integer i, iErr;
400 bApp = Standard_True;
401 bPC1 = Standard_True;
402 bPC2 = Standard_True;
403 aTol = BOPTest_Objects::FuzzyValue();
404 bRunParallel = BOPTest_Objects::RunParallel();
406 for (i = 4; i < n; ++i) {
407 if (!strcmp(a[i], "-n2d")) {
408 bPC1 = Standard_False;
409 bPC2 = Standard_False;
411 else if (!strcmp(a[i], "-n2d1")) {
412 bPC1 = Standard_False;
414 else if (!strcmp(a[i], "-n2d2")) {
415 bPC2 = Standard_False;
417 else if (!strcmp(a[i], "-na")) {
418 bApp = Standard_False;
421 aTol = Draw::Atof(a[i]);
425 BRepAlgoAPI_Section aSec(aS1, aS2, Standard_False);
427 aSec.Approximation(bApp);
428 aSec.ComputePCurveOn1(bPC1);
429 aSec.ComputePCurveOn2(bPC2);
430 aSec.SetFuzzyValue(aTol);
431 aSec.SetRunParallel(bRunParallel);
434 iErr=aSec.ErrorStatus();
435 if (!aSec.IsDone()) {
436 Sprintf(buf, " ErrorStatus : %d\n", iErr);
441 const TopoDS_Shape& aR=aSec.Shape();
443 di << " null shape\n";
446 DBRep::Set(a[1], aR);
449 //=======================================================================
452 //=======================================================================
453 Standard_Integer bsmt (Draw_Interpretor& di,
456 const BOPAlgo_Operation aOp)
459 Standard_Boolean bRunParallel;
460 Standard_Integer iErr;
461 TopoDS_Shape aS1, aS2;
462 BOPCol_ListOfShape aLC;
465 if (n < 4 || n > 5) {
466 di << " use bx r s1 s2 [tol]\n";
470 aS1=DBRep::Get(a[2]);
471 aS2=DBRep::Get(a[3]);
473 if (aS1.IsNull() || aS2.IsNull()) {
474 di << " null shapes are not allowed \n";
480 aTol=BOPTest_Objects::FuzzyValue();
482 aTol = Draw::Atof(a[4]);
485 bRunParallel = BOPTest_Objects::RunParallel();
487 Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
489 //---------------------------------------------------------------
490 BOPAlgo_PaveFiller aPF(aAL);
492 aPF.SetArguments(aLC);
493 aPF.SetFuzzyValue(aTol);
494 aPF.SetRunParallel(bRunParallel);
497 iErr=aPF.ErrorStatus();
499 Sprintf(buf, " ErrorStatus : %d\n", iErr);
504 //---------------------------------------------------------------
505 BOPAlgo_BOP aBOP(aAL);
507 aBOP.AddArgument(aS1);
509 aBOP.SetOperation(aOp);
510 aBOP.SetRunParallel(bRunParallel);
512 aBOP.PerformWithFiller(aPF);
514 iErr=aBOP.ErrorStatus();
516 Sprintf(buf, " ErrorStatus : %d\n", iErr);
520 const TopoDS_Shape& aR=aBOP.Shape();
522 di << " null shape\n";
526 DBRep::Set(a[1], aR);
529 //=======================================================================
532 //=======================================================================
533 Standard_Integer bopnews (Draw_Interpretor& di,
538 di << " use bopnews -v[e,f]\n";
543 di << " Prepare BOPAlgo_PaveFiller first >bop S1 S2\n";
548 Standard_CString aText;
549 Standard_Integer i, i1, i2, iFound;
550 Draw_Color aTextColor(Draw_cyan);
552 Handle(BOPTest_DrawableShape) aDShape;
554 const BOPDS_PDS& pDS=pPF->PDS();
557 if (!strcmp (a[1], "-f")) {
560 else if (!strcmp (a[1], "-e")){
563 else if (!strcmp (a[1], "-v")){
567 di << " use bopnews -v[e,f]\n";
572 i1=pDS->NbSourceShapes();
574 for (i=i1; i<i2; ++i) {
575 const BOPDS_ShapeInfo& aSI=pDS->ShapeInfo(i);
576 if (aSI.ShapeType()==aT) {
577 const TopoDS_Shape& aS=aSI.Shape();
579 Sprintf (buf, "z%d", i);
581 aDShape=new BOPTest_DrawableShape (aS, aText, aTextColor);
582 Draw::Set (aText, aDShape);
584 Sprintf (buf, " z%d", i);
595 di << " not found\n";
600 //=======================================================================
601 //function : bopcurves
603 //=======================================================================
604 Standard_Integer bopcurves (Draw_Interpretor& di,
609 di << " use bopcurves F1 F2 [-2d]\n";
613 TopoDS_Shape S1 = DBRep::Get(a[1]);
614 TopoDS_Shape S2 = DBRep::Get(a[2]);
615 TopAbs_ShapeEnum aType;
617 if (S1.IsNull() || S2.IsNull()) {
618 di << " Null shapes is not allowed \n";
622 aType=S1.ShapeType();
623 if (aType != TopAbs_FACE) {
624 di << " Type mismatch F1\n";
627 aType=S2.ShapeType();
628 if (aType != TopAbs_FACE) {
629 di << " Type mismatch F2\n";
634 const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
635 const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
637 Standard_Boolean aToApproxC3d, aToApproxC2dOnS1,
638 aToApproxC2dOnS2, anIsDone, bMake2dCurves;
639 Standard_Integer i, aNbCurves;
640 Standard_Real anAppTol, aTolR;
641 TCollection_AsciiString aNm("c_");
643 bMake2dCurves = Standard_False;
645 if (!strcasecmp(a[3],"-2d")) {
646 bMake2dCurves = Standard_True;
648 di << "Wrong key. To build 2d curves use: bopcurves F1 F2 -2d \n";
654 aToApproxC3d = Standard_True;
655 aToApproxC2dOnS1 = bMake2dCurves;
656 aToApproxC2dOnS2 = bMake2dCurves;
660 IntTools_FaceFace aFF;
662 aFF.SetParameters (aToApproxC3d,
667 aFF.Perform (aF1, aF2);
669 anIsDone=aFF.IsDone();
671 di << " anIsDone=" << (Standard_Integer) anIsDone << "\n";
675 aFF.PrepareLines3D(Standard_False);
676 const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
679 aTolR=aFF.TolReached3d();
680 di << "Tolerance Reached=" << aTolR << "\n";
682 aNbCurves=aSCs.Length();
684 di << " has no 3d curve\n";
688 di << aNbCurves << " curve(s) found.\n";
691 for (i=1; i<=aNbCurves; i++) {
692 const IntTools_Curve& anIC=aSCs(i);
694 Handle (Geom_Curve) aC3D = anIC.Curve();
697 di << " has Null 3d curve# " << i << "\n";
701 TCollection_AsciiString anIndx(i), aNmx;
704 Standard_CString nameC = aNmx.ToCString();
706 DrawTrSurf::Set(nameC, aC3D);
710 Handle(Geom2d_Curve) aPC1 = anIC.FirstCurve2d();
711 Handle(Geom2d_Curve) aPC2 = anIC.SecondCurve2d();
713 if (aPC1.IsNull() && aPC2.IsNull()) {
714 di << " \n has Null 2d curves# " << i << "\n";
719 TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
720 pc2Nx = pc2N + anIndx;
721 Standard_CString nameC2d2 = pc2Nx.ToCString();
723 DrawTrSurf::Set(nameC2d2, aPC2);
724 di << "(" << nameC2d2 << ") ";
725 di << " \n Null first 2d curve of the curve #" << i << "\n";
729 TCollection_AsciiString pc1N("c2d1_"), pc1Nx;
730 pc1Nx = pc1N + anIndx;
731 Standard_CString nameC2d1 = pc1Nx.ToCString();
733 DrawTrSurf::Set(nameC2d1, aPC1);
734 di << "(" << nameC2d1;
738 di << ") \n Null second 2d curve of the curve #" << i << "\n";
742 TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
743 pc2Nx = pc2N + anIndx;
744 Standard_CString nameC2d2 = pc2Nx.ToCString();
746 DrawTrSurf::Set(nameC2d2, aPC2);
747 di << ", " << nameC2d2 << ") ";
756 //=======================================================================
757 //function : mkvolume
759 //=======================================================================
760 Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char** a)
763 di << "Usage: mkvolume r b1 b2 ... [-c] [-ni] [-s] [tol]\n";
765 di << " -c - use this option if the arguments are compounds\n";
766 di << " containing shapes that should be interfered;\n";
767 di << " -ni - use this option if the arguments should not be interfered;\n";
768 di << " -s - use this option to run the operation in non parallel mode;\n";
769 di << " tol - additional tolerance value (real).\n";
773 const char* usage = "Type mkvolume without arguments for the usage of the command.\n";
775 Standard_Boolean bToIntersect, bRunParallel, bCompounds;
779 BOPCol_ListOfShape aLS;
781 aTol = BOPTest_Objects::FuzzyValue();
782 bToIntersect = Standard_True;
783 bRunParallel = BOPTest_Objects::RunParallel();
784 bCompounds = Standard_False;
786 for (i = 2; i < n; ++i) {
787 aS = DBRep::Get(a[i]);
792 if (!strcmp(a[i], "-c")) {
793 bCompounds = Standard_True;
795 else if (!strcmp(a[i], "-ni")) {
796 bToIntersect = Standard_False;
798 else if (!strcmp(a[i], "-s")) {
799 bRunParallel = Standard_False;
802 aTol = Draw::Atof(a[i]);
808 di << "No shapes to process.\n";
813 // treat list of arguments for the case of compounds
814 if (bToIntersect && bCompounds) {
815 BOPCol_ListOfShape aLSx;
816 BOPCol_ListIteratorOfListOfShape aItLS;
818 aItLS.Initialize(aLS);
819 for (; aItLS.More(); aItLS.Next()) {
820 const TopoDS_Shape& aSx = aItLS.Value();
821 TopoDS_Iterator aItS(aSx);
822 for (; aItS.More(); aItS.Next()) {
823 const TopoDS_Shape& aSxS = aItS.Value();
832 BOPAlgo_MakerVolume aMV;
833 aMV.SetArguments(aLS);
834 aMV.SetIntersect(bToIntersect);
835 aMV.SetRunParallel(bRunParallel);
836 aMV.SetFuzzyValue(aTol);
839 if (aMV.ErrorStatus()) {
840 di << "Error status: " << aMV.ErrorStatus();
844 const TopoDS_Shape& aR = aMV.Shape();
846 DBRep::Set(a[1], aR);
850 //=======================================================================
851 //function : bparallelmode
853 //=======================================================================
854 Standard_Integer bparallelmode(Draw_Interpretor& di, Standard_Integer n, const char** a)
858 Standard_Boolean isParallelOn = Draw::Atoi (a[1]) == 1;
859 if (isParallelOn == 1)
861 BOPAlgo_Algo::SetParallelMode(Standard_True);
862 di << "Parallel mode for boolean operations has been enabled";
866 BOPAlgo_Algo::SetParallelMode(Standard_False);
867 di << "Parallel mode for boolean operations has been disabled";
872 di << "Parallel mode state for boolean operations: "
873 << (BOPAlgo_Algo::GetParallelMode()? "enabled" : "disabled");