0025354: Intersection operation
[occt.git] / src / BOPTest / BOPTest_BOPCommands.cxx
1 // Created on: 2000-03-16
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BOPTest.ixx>
17
18 #include <stdio.h>
19
20 #include <DBRep.hxx>
21
22 #include <NCollection_BaseAllocator.hxx>
23 #include <NCollection_IncAllocator.hxx>
24
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Compound.hxx>
27 #include <BRep_Builder.hxx>
28
29 #include <BOPAlgo_PaveFiller.hxx>
30 #include <BOPAlgo_Operation.hxx>
31 #include <BOPAlgo_BOP.hxx>
32 #include <BOPAlgo_MakerVolume.hxx>
33 #include <BOPDS_DS.hxx>
34 #include <BOPTest_DrawableShape.hxx>
35 #include <BOPCol_ListOfShape.hxx>
36
37 #include <TCollection_AsciiString.hxx>
38 #include <IntTools_FaceFace.hxx>
39 #include <IntTools_Curve.hxx>
40 #include <DrawTrSurf.hxx>
41 #include <Draw_Color.hxx>
42 #include <Draw.hxx>
43 #include <BRepAlgoAPI_BooleanOperation.hxx>
44 #include <BRepAlgoAPI_Common.hxx>
45 #include <BRepAlgoAPI_Fuse.hxx>
46 #include <BRepAlgoAPI_Cut.hxx>
47 #include <BRepAlgoAPI_Section.hxx>
48 #include <BOPAlgo_Section.hxx>
49
50 //
51 static BOPAlgo_PaveFiller* pPF=NULL;
52 //
53
54 static
55   Standard_Integer bopsmt(Draw_Interpretor& di,
56                           Standard_Integer n,
57                           const char** a,
58                           const BOPAlgo_Operation aOp);
59 static
60   Standard_Integer bsmt (Draw_Interpretor& di, 
61                        Standard_Integer n, 
62                        const char** a,
63                        const BOPAlgo_Operation aOp);
64 //
65 static Standard_Integer bop       (Draw_Interpretor&, Standard_Integer, const char**);
66 static Standard_Integer bopsection(Draw_Interpretor&, Standard_Integer, const char**);
67 static Standard_Integer boptuc    (Draw_Interpretor&, Standard_Integer, const char**);
68 static Standard_Integer bopcut    (Draw_Interpretor&, Standard_Integer, const char**);
69 static Standard_Integer bopfuse   (Draw_Interpretor&, Standard_Integer, const char**);
70 static Standard_Integer bopcommon (Draw_Interpretor&, Standard_Integer, const char**);
71 //
72 static Standard_Integer bsection  (Draw_Interpretor&, Standard_Integer, const char**);
73 static Standard_Integer btuc      (Draw_Interpretor&, Standard_Integer, const char**);
74 static Standard_Integer bcut      (Draw_Interpretor&, Standard_Integer, const char**);
75 static Standard_Integer bfuse     (Draw_Interpretor&, Standard_Integer, const char**);
76 static Standard_Integer bcommon   (Draw_Interpretor&, Standard_Integer, const char**);
77 //
78 static Standard_Integer bopcurves (Draw_Interpretor&, Standard_Integer, const char**);
79 static Standard_Integer bopnews   (Draw_Interpretor&, Standard_Integer, const char**);
80 //
81 static Standard_Integer bparallelmode(Draw_Interpretor&, Standard_Integer, const char**);
82 //
83 static Standard_Integer mkvolume   (Draw_Interpretor&, Standard_Integer, const char**);
84
85 //=======================================================================
86 //function : BOPCommands
87 //purpose  : 
88 //=======================================================================
89   void BOPTest::BOPCommands(Draw_Interpretor& theCommands)
90 {
91   static Standard_Boolean done = Standard_False;
92   if (done) return;
93   done = Standard_True;
94   // Chapter's name
95   const char* g = "BOP commands";
96   // Commands
97   
98   theCommands.Add("bop"       , "use bop s1 s2"   , __FILE__, bop, g);
99   theCommands.Add("bopcommon" , "use bopcommon r" , __FILE__, bopcommon, g);
100   theCommands.Add("bopfuse"   , "use bopfuse r"   , __FILE__,bopfuse, g);
101   theCommands.Add("bopcut"    , "use bopcut"      , __FILE__,bopcut, g);
102   theCommands.Add("boptuc"    , "use boptuc"      , __FILE__,boptuc, g);
103   theCommands.Add("bopsection", "use bopsection"  , __FILE__,bopsection, g);
104   //
105   theCommands.Add("bcommon" , "use bcommon r s1 s2" , __FILE__,bcommon, g);
106   theCommands.Add("bfuse"   , "use bfuse r s1 s2"   , __FILE__,bfuse, g);
107   theCommands.Add("bcut"    , "use bcut r s1 s2"    , __FILE__,bcut, g);
108   theCommands.Add("btuc"    , "use btuc r s1 s2"    , __FILE__,btuc, g);
109   theCommands.Add("bsection", "Use >bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]", 
110                                                       __FILE__, bsection, g);
111   //
112   theCommands.Add("bopcurves", "use  bopcurves F1 F2 [-2d]", __FILE__, bopcurves, g);
113   theCommands.Add("bopnews", "use  bopnews -v[e,f]"  , __FILE__, bopnews, g);
114   theCommands.Add("bparallelmode", "bparallelmode [1/0] : show / set parallel mode for boolean operations", __FILE__, bparallelmode, g);
115   theCommands.Add("mkvolume", "make solids from set of shapes.\nmkvolume r b1 b2 ... [-ni (do not intersect)] [-s (run in non parallel mode)]", __FILE__, mkvolume , g);
116 }
117
118 //=======================================================================
119 //function : bop
120 //purpose  : 
121 //=======================================================================
122 Standard_Integer bop (Draw_Interpretor& di, Standard_Integer n, const char** a)
123 {
124   char buf[32];
125   Standard_Integer iErr;
126   TopoDS_Shape aS1, aS2;
127   BOPCol_ListOfShape aLC;
128   //
129   if (n!=3) {
130     di << " use bop Shape1 Shape2\n";
131     return 1;
132   }
133   //
134   aS1=DBRep::Get(a[1]);
135   aS2=DBRep::Get(a[2]);
136   //
137   if (aS1.IsNull() || aS2.IsNull()) {
138     di << " null shapes are not allowed \n";
139     return 1;
140   }
141   //
142   aLC.Append(aS1);
143   aLC.Append(aS2);
144   //
145   if (pPF!=NULL) {
146     delete pPF;
147     pPF=NULL;
148   }
149   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
150   pPF=new BOPAlgo_PaveFiller(aAL);
151   //
152   pPF->SetArguments(aLC);
153   //
154   pPF->Perform();
155   iErr=pPF->ErrorStatus();
156   if (iErr) {
157     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
158     di << buf;
159     return 0;
160   }
161   //
162   return 0;
163 }
164 //=======================================================================
165 //function : bopcommon
166 //purpose  : 
167 //=======================================================================
168 Standard_Integer bopcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
169 {
170   return bopsmt(di, n, a, BOPAlgo_COMMON);
171 }
172 //=======================================================================
173 //function : bopfuse
174 //purpose  : 
175 //=======================================================================
176 Standard_Integer bopfuse(Draw_Interpretor& di, Standard_Integer n, const char** a)
177 {
178   return bopsmt(di, n, a, BOPAlgo_FUSE);
179 }
180 //=======================================================================
181 //function : bopcut
182 //purpose  : 
183 //=======================================================================
184 Standard_Integer bopcut(Draw_Interpretor& di, Standard_Integer n, const char** a)
185 {
186   return bopsmt(di, n, a, BOPAlgo_CUT);
187 }
188 //=======================================================================
189 //function : boptuc
190 //purpose  : 
191 //=======================================================================
192 Standard_Integer boptuc(Draw_Interpretor& di, Standard_Integer n, const char** a)
193 {
194   return bopsmt(di, n, a, BOPAlgo_CUT21);
195 }
196 //=======================================================================
197 //function : bopsmt
198 //purpose  : 
199 //=======================================================================
200 Standard_Integer bopsmt(Draw_Interpretor& di,
201                         Standard_Integer n,
202                         const char** a,
203                         const BOPAlgo_Operation aOp)
204 {
205   if (n<2) {
206     di << " use bopsmt r\n";
207     return 0;
208   }
209   //
210   if (!pPF) {
211     di << " prepare PaveFiller first\n";
212     return 0;
213   }
214   //
215   if (pPF->ErrorStatus()) {
216     di << " PaveFiller has not been done\n";
217     return 0;
218   }
219   //
220   char buf[64];
221   Standard_Integer aNb, iErr;
222   BOPAlgo_BOP aBOP;
223   //
224   const BOPCol_ListOfShape& aLC=pPF->Arguments();
225   aNb=aLC.Extent();
226   if (aNb!=2) {
227     Sprintf (buf, " wrong number of arguments %s\n", aNb);
228     di << buf;
229     return 0;
230   }
231   //
232   const TopoDS_Shape& aS1=aLC.First();
233   const TopoDS_Shape& aS2=aLC.Last();
234   //
235   aBOP.AddArgument(aS1);
236   aBOP.AddTool(aS2);
237   aBOP.SetOperation(aOp);
238   //
239   aBOP.PerformWithFiller(*pPF);
240   iErr=aBOP.ErrorStatus();
241   if (iErr) {
242     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
243     di << buf;
244     return 0;
245   }
246   //
247   const TopoDS_Shape& aR=aBOP.Shape();
248   if (aR.IsNull()) {
249     di << " null shape\n";
250     return 0;
251   }
252   //
253   DBRep::Set(a[1], aR);
254   return 0;
255 }
256 //=======================================================================
257 //function : bopsection
258 //purpose  : 
259 //=======================================================================
260 Standard_Integer bopsection(Draw_Interpretor& di, Standard_Integer n, const char** a)
261 {
262   if (n<2) {
263     di << " use bopsmt r\n";
264     return 0;
265   }
266   //
267   if (!pPF) {
268     di << " prepare PaveFiller first\n";
269     return 0;
270   }
271   //
272   if (pPF->ErrorStatus()) {
273     di << " PaveFiller has not been done\n";
274     return 0;
275   }
276   //
277   char buf[64];
278   Standard_Integer aNb, iErr;
279   BOPAlgo_Section aBOP;
280   //
281   const BOPCol_ListOfShape& aLC=pPF->Arguments();
282   aNb=aLC.Extent();
283   if (aNb!=2) {
284     Sprintf (buf, " wrong number of arguments %s\n", aNb);
285     di << buf;
286     return 0;
287   }
288   //
289   const TopoDS_Shape& aS1=aLC.First();
290   const TopoDS_Shape& aS2=aLC.Last();
291   //
292   aBOP.AddArgument(aS1);
293   aBOP.AddArgument(aS2);
294   //
295   aBOP.PerformWithFiller(*pPF);
296   iErr=aBOP.ErrorStatus();
297   if (iErr) {
298     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
299     di << buf;
300     return 0;
301   }
302   //
303   const TopoDS_Shape& aR=aBOP.Shape();
304   if (aR.IsNull()) {
305     di << " null shape\n";
306     return 0;
307   }
308   //
309   DBRep::Set(a[1], aR);
310   return 0;
311 }
312 //=======================================================================
313 //function : bcommon
314 //purpose  : 
315 //=======================================================================
316 Standard_Integer bcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
317 {
318   return bsmt(di, n, a, BOPAlgo_COMMON);
319 }
320 //=======================================================================
321 //function : bfuse
322 //purpose  : 
323 //=======================================================================
324 Standard_Integer bfuse (Draw_Interpretor& di, Standard_Integer n, const char** a)
325 {
326   return bsmt(di, n, a, BOPAlgo_FUSE);
327 }
328 //=======================================================================
329 //function : bcut
330 //purpose  : 
331 //=======================================================================
332 Standard_Integer bcut (Draw_Interpretor& di, Standard_Integer n, const char** a)
333 {
334   return bsmt(di, n, a, BOPAlgo_CUT);
335 }
336 //=======================================================================
337 //function : btuc
338 //purpose  : 
339 //=======================================================================
340 Standard_Integer btuc (Draw_Interpretor& di, Standard_Integer n, const char** a)
341 {
342   return bsmt(di, n, a, BOPAlgo_CUT21);
343 }
344 //=======================================================================
345 //function : bsection
346 //purpose  : 
347 //=======================================================================
348 Standard_Integer  bsection(Draw_Interpretor& di, 
349                            Standard_Integer n, 
350                            const char** a)
351 {
352   const char* usage = " Usage: bsection Result s1 s2 [-n2d/-n2d1/-n2d2] [-na]\n";
353   if (n < 4) {
354     di << usage;
355     return 1;
356   }
357
358   TopoDS_Shape aS1 = DBRep::Get(a[2]);
359   TopoDS_Shape aS2 = DBRep::Get(a[3]);
360   
361   if (aS1.IsNull() || aS2.IsNull()) {
362     di << " Null shapes are not allowed \n";
363     return 1;
364   }
365
366   Standard_Boolean bApp, bPC1, bPC2;
367   //
368   bApp = Standard_True;
369   bPC1 = Standard_True;
370   bPC2 = Standard_True;
371   
372   Standard_Boolean isbadparameter = Standard_False;
373   
374   if(n > 4) {
375     const char* key1 = a[4];
376     const char* key2 = (n > 5) ? a[5] : NULL;
377     const char* pcurveconf = NULL;
378
379     if (key1 && 
380         (!strcasecmp(key1,"-n2d") || 
381          !strcasecmp(key1,"-n2d1") || 
382          !strcasecmp(key1,"-n2d2"))) {
383       pcurveconf = key1;
384     }
385     else {
386       if (!strcasecmp(key1,"-na")) {
387         bApp = Standard_False;
388       }
389       else {
390         isbadparameter = Standard_True;
391       }
392     }
393     if (key2) {
394       if(!strcasecmp(key2,"-na")) {
395         bApp = Standard_False;
396       }
397       else {
398         isbadparameter = Standard_True;
399       }
400     }
401
402     if(!isbadparameter && pcurveconf) {      
403       if (!strcasecmp(pcurveconf, "-n2d1")) {
404         bPC1 = Standard_False;
405       }
406       else {
407         if (!strcasecmp(pcurveconf, "-n2d2")) {
408           bPC2 = Standard_False;
409         }
410         else {
411           if (!strcasecmp(pcurveconf, "-n2d")) {
412             bPC1 = Standard_False;
413             bPC2 = Standard_False;
414           }
415         }
416       }
417     }
418   }
419       
420   if(!isbadparameter) {
421     Standard_Integer iErr;
422     char buf[80];
423     //
424     BRepAlgoAPI_Section aSec(aS1, aS2, Standard_False);
425     aSec.Approximation(bApp);
426     aSec.ComputePCurveOn1(bPC1);
427     aSec.ComputePCurveOn2(bPC2);
428     //
429     aSec.Build();
430     iErr=aSec.ErrorStatus();
431     if (!aSec.IsDone()) {
432       Sprintf(buf, " ErrorStatus : %d\n",  iErr);
433       di << buf;
434       return 0;
435     }
436     //
437     const TopoDS_Shape& aR=aSec.Shape();
438     if (aR.IsNull()) {
439       di << " null shape\n";
440       return 0;
441     }
442     DBRep::Set(a[1], aR);
443     return 0;
444   }
445   else {
446     di << usage;
447     return 1;
448   }
449 }
450 //=======================================================================
451 //function : bsmt
452 //purpose  : 
453 //=======================================================================
454 Standard_Integer bsmt (Draw_Interpretor& di, 
455                        Standard_Integer n, 
456                        const char** a,
457                        const BOPAlgo_Operation aOp)
458 {
459   char buf[32];
460   Standard_Integer iErr;
461   TopoDS_Shape aS1, aS2;
462   BOPCol_ListOfShape aLC;
463   //
464   if (n!=4) {
465     di << " use bx r s1 s2\n";
466     return 1;
467   }
468   //
469   aS1=DBRep::Get(a[2]);
470   aS2=DBRep::Get(a[3]);
471   //
472   if (aS1.IsNull() || aS2.IsNull()) {
473     di << " null shapes are not allowed \n";
474     return 1;
475   }
476   aLC.Append(aS1);
477   aLC.Append(aS2);
478   //
479   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
480   BOPAlgo_PaveFiller aPF(aAL);
481   //
482   aPF.SetArguments(aLC);
483   //
484   aPF.Perform();
485   iErr=aPF.ErrorStatus();
486   if (iErr) {
487     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
488     di << buf;
489     return 0;
490   }
491   //
492   BRepAlgoAPI_BooleanOperation* pBuilder=NULL;
493   // 
494   if (aOp==BOPAlgo_COMMON) {
495     pBuilder=new BRepAlgoAPI_Common(aS1, aS2, aPF);
496   }
497   else if (aOp==BOPAlgo_FUSE) {
498     pBuilder=new BRepAlgoAPI_Fuse(aS1, aS2, aPF);
499   }
500   else if (aOp==BOPAlgo_CUT) {
501     pBuilder=new BRepAlgoAPI_Cut (aS1, aS2, aPF);
502   }
503   else if (aOp==BOPAlgo_CUT21) {
504     pBuilder=new BRepAlgoAPI_Cut(aS1, aS2, aPF, Standard_False);
505   }
506   //
507   iErr = pBuilder->ErrorStatus();
508   if (!pBuilder->IsDone()) {
509     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
510     di << buf;
511     return 0;
512   }
513   const TopoDS_Shape& aR=pBuilder->Shape();
514   if (aR.IsNull()) {
515     di << " null shape\n";
516     return 0;
517   }
518   DBRep::Set(a[1], aR);
519   return 0;
520 }
521
522 //=======================================================================
523 //function : bopnews
524 //purpose  : 
525 //=======================================================================
526 Standard_Integer bopnews (Draw_Interpretor& di, 
527                           Standard_Integer n, 
528                           const char** a)
529 {
530   if (n!=2) {
531     di << " use bopnews -v[e,f]\n";
532     return 0;
533   }
534   //
535   if (pPF==NULL) {
536     di << " Prepare BOPAlgo_PaveFiller first >bop S1 S2\n";
537     return 0;
538   }
539   //
540   char buf[32];
541   Standard_CString aText;
542   Standard_Integer i, i1, i2, iFound;
543   Draw_Color aTextColor(Draw_cyan);
544   TopAbs_ShapeEnum aT;
545   Handle(BOPTest_DrawableShape) aDShape;
546   //
547   const BOPDS_PDS& pDS=pPF->PDS();
548   //
549   aT=TopAbs_SHAPE;
550   if (!strcmp (a[1], "-f")) {
551     aT=TopAbs_FACE;
552   }
553   else if (!strcmp (a[1], "-e")){
554     aT=TopAbs_EDGE;
555   }
556   else if (!strcmp (a[1], "-v")){
557     aT=TopAbs_VERTEX;
558   }
559   else {
560     di << " use bopnews -v[e,f]\n";
561     return 0;
562   }
563   //
564   iFound=0;
565   i1=pDS->NbSourceShapes();
566   i2=pDS->NbShapes();
567   for (i=i1; i<i2; ++i) {
568     const BOPDS_ShapeInfo& aSI=pDS->ShapeInfo(i);
569     if (aSI.ShapeType()==aT) {
570       const TopoDS_Shape& aS=aSI.Shape();
571       //
572       Sprintf (buf, "z%d", i);
573       aText=buf;
574       aDShape=new BOPTest_DrawableShape (aS, aText, aTextColor);
575       Draw::Set (aText, aDShape);
576       //
577       Sprintf (buf, " z%d", i);
578       di << buf;
579       //
580       iFound=1;
581     }
582   }
583   //
584   if (iFound) {
585     di << "\n";
586   }
587   else {
588     di << " not found\n";
589   }
590   //
591   return 0;
592 }
593
594 //=======================================================================
595 //function : bopcurves
596 //purpose  : 
597 //=======================================================================
598 Standard_Integer bopcurves (Draw_Interpretor& di, 
599                             Standard_Integer n, 
600                             const char** a)
601 {
602   if (n<3) {
603     di << " use bopcurves F1 F2 [-2d]\n";
604     return 1;
605   }
606
607   TopoDS_Shape S1 = DBRep::Get(a[1]);
608   TopoDS_Shape S2 = DBRep::Get(a[2]);
609   TopAbs_ShapeEnum aType;
610
611   if (S1.IsNull() || S2.IsNull()) {
612     di << " Null shapes is not allowed \n";
613     return 1;
614   }
615
616   aType=S1.ShapeType();
617   if (aType != TopAbs_FACE) {
618     di << " Type mismatch F1\n";
619     return 1;
620   }
621   aType=S2.ShapeType();
622   if (aType != TopAbs_FACE) {
623     di << " Type mismatch F2\n";
624     return 1;
625   }
626
627
628   const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
629   const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
630
631   Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone, bMake2dCurves;
632   Standard_Integer i, aNbCurves;
633   Standard_Real anAppTol, aTolR;
634   TCollection_AsciiString aNm("c_");
635
636   bMake2dCurves = Standard_False;
637   if (n > 3) {
638     if (!strcasecmp(a[3],"-2d")) {
639       bMake2dCurves = Standard_True;
640     } else {
641       di << "Wrong key. To build 2d curves use: bopcurves F1 F2 -2d \n";
642       return 1;
643     }
644   }
645   //
646
647   aToApproxC3d = Standard_True;
648   aToApproxC2dOnS1 = bMake2dCurves;
649   aToApproxC2dOnS2 = bMake2dCurves;
650   anAppTol=0.0000001;
651
652
653   IntTools_FaceFace aFF;
654   
655   aFF.SetParameters (aToApproxC3d,
656                      aToApproxC2dOnS1,
657                      aToApproxC2dOnS2,
658                      anAppTol);
659   
660   aFF.Perform (aF1, aF2);
661   
662   anIsDone=aFF.IsDone();
663   if (!anIsDone) {
664     di << " anIsDone=" << (Standard_Integer) anIsDone << "\n";
665     return 1;
666   }
667
668   aFF.PrepareLines3D(Standard_False);
669   const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
670
671   //
672   aTolR=aFF.TolReached3d();
673   di << "Tolerance Reached=" << aTolR << "\n";
674
675   aNbCurves=aSCs.Length();
676   if (!aNbCurves) {
677     di << " has no 3d curve\n";
678     return 1;
679   }
680   else
681   {
682     di << aNbCurves << " curve(s) found.\n";
683   }
684
685   for (i=1; i<=aNbCurves; i++) {
686     const IntTools_Curve& anIC=aSCs(i);
687
688     Handle (Geom_Curve)  aC3D = anIC.Curve();
689
690     if (aC3D.IsNull()) {
691       di << " has Null 3d curve# " << i << "\n";
692       continue;
693     }
694
695     TCollection_AsciiString anIndx(i), aNmx;
696     aNmx = aNm + anIndx;
697
698     Standard_CString nameC = aNmx.ToCString();
699
700     DrawTrSurf::Set(nameC, aC3D);
701     di << nameC << " ";
702     //
703     if (bMake2dCurves) {
704       Handle(Geom2d_Curve) aPC1 = anIC.FirstCurve2d();
705       Handle(Geom2d_Curve) aPC2 = anIC.SecondCurve2d();
706       //
707       if (aPC1.IsNull() && aPC2.IsNull()) {
708         di << " \n has Null 2d curves# " << i << "\n";
709         continue;
710       }
711       //
712       if (aPC1.IsNull()) {
713         TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
714         pc2Nx = pc2N + anIndx;
715         Standard_CString nameC2d2 = pc2Nx.ToCString();
716         //
717         DrawTrSurf::Set(nameC2d2, aPC2);
718         di << "(" << nameC2d2 << ") ";
719         di << " \n Null first 2d curve of the curve #" << i << "\n";
720         continue;
721       } else {
722         TCollection_AsciiString pc1N("c2d1_"), pc1Nx;
723         pc1Nx = pc1N + anIndx;
724         Standard_CString nameC2d1 = pc1Nx.ToCString();
725         //
726         DrawTrSurf::Set(nameC2d1, aPC1);
727         di << "(" << nameC2d1;
728       }
729       //
730       if (aPC2.IsNull()) {
731         di << ") \n Null second 2d curve of the curve #" << i << "\n";
732         continue;
733       } else {
734         TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
735         pc2Nx = pc2N + anIndx;
736         Standard_CString nameC2d2 = pc2Nx.ToCString();
737         //
738         DrawTrSurf::Set(nameC2d2, aPC2);
739         di << ", " << nameC2d2 << ") ";
740       }
741     }
742   }
743
744   di << "\n";
745   
746   return 0;
747 }
748
749 //=======================================================================
750 //function : bparallelmode
751 //purpose  : 
752 //=======================================================================
753 Standard_Integer bparallelmode(Draw_Interpretor& di, Standard_Integer n, const char** a)
754 {
755   if (n == 2)
756   {
757     Standard_Boolean isParallelOn = Draw::Atoi (a[1]) == 1;
758     if (isParallelOn == 1)
759     {
760       BOPAlgo_Algo::SetParallelMode(Standard_True);
761       di << "Parallel mode for boolean operations has been enabled";
762     }
763     else
764     {
765       BOPAlgo_Algo::SetParallelMode(Standard_False);
766       di << "Parallel mode for boolean operations has been disabled";
767     }
768   }
769   else
770   {
771     di << "Parallel mode state for boolean operations: "
772        << (BOPAlgo_Algo::GetParallelMode()? "enabled" : "disabled");
773   }
774
775   return 0;
776 }
777
778 //=======================================================================
779 //function : mkvolume
780 //purpose  : 
781 //=======================================================================
782 Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char** a) 
783 {
784   const char* usage = "Usage: mkvolume r b1 b2 ... [-ni (do not intersect)] [-s (run in non parallel mode)]\n";
785   if (n < 3) {
786     di << usage;
787     return 1;
788   }
789   //
790   Standard_Boolean bToIntersect, bRunParallel;
791   Standard_Integer i, aNb;
792   //
793   aNb = n;
794   bToIntersect = Standard_True;
795   bRunParallel = Standard_True;
796   //
797   if (!strcmp(a[n-1], "-ni")) {
798     bToIntersect = Standard_False;
799     aNb = n-1;
800   } 
801   else if (!strcmp(a[n-1], "-s")) {
802     bRunParallel = Standard_False;
803     aNb = n-1;
804   }
805   if (n > 3) {
806     if (!strcmp(a[n-2], "-ni")) {
807       bToIntersect = Standard_False;
808       aNb = n-2;
809     } 
810     else if (!strcmp(a[n-2], "-s")) {
811       bRunParallel = Standard_False;
812       aNb = n-2;
813     }
814   }
815   //
816   if (aNb < 3) {
817     di << "no shapes to process.\n";
818     di << usage;
819     return 1;
820   }
821   //
822   BOPCol_ListOfShape aLS;
823   TopoDS_Shape aS;
824   for (i = 2; i < aNb; ++i) {
825     aS = DBRep::Get(a[i]);
826     if (!aS.IsNull()) {
827       aLS.Append(aS);
828     }
829   }
830   //
831   if (aLS.IsEmpty()) {
832     di << "no shapes to process.\n";
833     di << usage;
834     return 1;
835   }
836   //
837   BOPAlgo_MakerVolume aMV;
838   aMV.SetArguments(aLS);
839   aMV.SetIntersect(bToIntersect);
840   aMV.SetRunParallel(bRunParallel);
841   //
842   aMV.Perform();
843   if (aMV.ErrorStatus()) {
844     di << "Error status: " << aMV.ErrorStatus();
845     return 1;
846   }
847   //
848   const TopoDS_Shape& aR = aMV.Shape();
849   //
850   DBRep::Set(a[1], aR);
851   //
852   return 0;
853 }
854