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