bcd8aa10305a38362aed4f63e6758281e288b170
[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
8 // under the terms of the GNU Lesser General Public 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 <BOPDS_DS.hxx>
33 #include <BOPTest_DrawableShape.hxx>
34 #include <BOPCol_ListOfShape.hxx>
35
36 #include <TCollection_AsciiString.hxx>
37 #include <IntTools_FaceFace.hxx>
38 #include <IntTools_Curve.hxx>
39 #include <DrawTrSurf.hxx>
40 #include <Draw_Color.hxx>
41 #include <Draw.hxx>
42 #include <BRepAlgoAPI_BooleanOperation.hxx>
43 #include <BRepAlgoAPI_Common.hxx>
44 #include <BRepAlgoAPI_Fuse.hxx>
45 #include <BRepAlgoAPI_Cut.hxx>
46 #include <BRepAlgoAPI_Section.hxx>
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 static
58   Standard_Integer bsmt (Draw_Interpretor& di, 
59                        Standard_Integer n, 
60                        const char** a,
61                        const BOPAlgo_Operation aOp);
62 //
63 static Standard_Integer bop       (Draw_Interpretor&, Standard_Integer, const char**);
64 static Standard_Integer bopsection(Draw_Interpretor&, Standard_Integer, const char**);
65 static Standard_Integer boptuc    (Draw_Interpretor&, Standard_Integer, const char**);
66 static Standard_Integer bopcut    (Draw_Interpretor&, Standard_Integer, const char**);
67 static Standard_Integer bopfuse   (Draw_Interpretor&, Standard_Integer, const char**);
68 static Standard_Integer bopcommon (Draw_Interpretor&, Standard_Integer, const char**);
69 //
70 static Standard_Integer bsection  (Draw_Interpretor&, Standard_Integer, const char**);
71 static Standard_Integer btuc      (Draw_Interpretor&, Standard_Integer, const char**);
72 static Standard_Integer bcut      (Draw_Interpretor&, Standard_Integer, const char**);
73 static Standard_Integer bfuse     (Draw_Interpretor&, Standard_Integer, const char**);
74 static Standard_Integer bcommon   (Draw_Interpretor&, Standard_Integer, const char**);
75 //
76 static Standard_Integer bopcurves (Draw_Interpretor&, Standard_Integer, const char**);
77 static Standard_Integer bopnews   (Draw_Interpretor&, Standard_Integer, const char**);
78
79 //=======================================================================
80 //function : BOPCommands
81 //purpose  : 
82 //=======================================================================
83   void BOPTest::BOPCommands(Draw_Interpretor& theCommands)
84 {
85   static Standard_Boolean done = Standard_False;
86   if (done) return;
87   done = Standard_True;
88   // Chapter's name
89   const char* g = "BOP commands";
90   // Commands
91   
92   theCommands.Add("bop"       , "use bop s1 s2"   , __FILE__, bop, g);
93   theCommands.Add("bopcommon" , "use bopcommon r" , __FILE__, bopcommon, g);
94   theCommands.Add("bopfuse"   , "use bopfuse r"   , __FILE__,bopfuse, g);
95   theCommands.Add("bopcut"    , "use bopcut"      , __FILE__,bopcut, g);
96   theCommands.Add("boptuc"    , "use boptuc"      , __FILE__,boptuc, g);
97   theCommands.Add("bopsection", "use bopsection"  , __FILE__,bopsection, g);
98   //
99   theCommands.Add("bcommon" , "use bcommon r s1 s2" , __FILE__,bcommon, g);
100   theCommands.Add("bfuse"   , "use bfuse r s1 s2"   , __FILE__,bfuse, g);
101   theCommands.Add("bcut"    , "use bcut r s1 s2"    , __FILE__,bcut, g);
102   theCommands.Add("btuc"    , "use btuc r s1 s2"    , __FILE__,btuc, g);
103   theCommands.Add("bsection", "Use >bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]", 
104                                                       __FILE__, bsection, g);
105   //
106   theCommands.Add("bopcurves", "use  bopcurves F1 F2 [-2d]", __FILE__, bopcurves, g);
107   theCommands.Add("bopnews", "use  bopnews -v[e,f]"  , __FILE__, bopnews, g);
108 }
109
110 //=======================================================================
111 //function : bop
112 //purpose  : 
113 //=======================================================================
114 Standard_Integer bop (Draw_Interpretor& di, Standard_Integer n, const char** a)
115 {
116   char buf[32];
117   Standard_Integer iErr;
118   TopoDS_Shape aS1, aS2;
119   BOPCol_ListOfShape aLC;
120   //
121   if (n!=3) {
122     di << " use bop Shape1 Shape2\n";
123     return 1;
124   }
125   //
126   aS1=DBRep::Get(a[1]);
127   aS2=DBRep::Get(a[2]);
128   //
129   if (aS1.IsNull() || aS2.IsNull()) {
130     di << " null shapes are not allowed \n";
131     return 1;
132   }
133   //
134   aLC.Append(aS1);
135   aLC.Append(aS2);
136   //
137   if (pPF!=NULL) {
138     delete pPF;
139     pPF=NULL;
140   }
141   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
142   pPF=new BOPAlgo_PaveFiller(aAL);
143   //
144   pPF->SetArguments(aLC);
145   //
146   pPF->Perform();
147   iErr=pPF->ErrorStatus();
148   if (iErr) {
149     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
150     di << buf;
151     return 0;
152   }
153   //
154   return 0;
155 }
156 //=======================================================================
157 //function : bopcommon
158 //purpose  : 
159 //=======================================================================
160 Standard_Integer bopcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
161 {
162   return bopsmt(di, n, a, BOPAlgo_COMMON);
163 }
164 //=======================================================================
165 //function : bopfuse
166 //purpose  : 
167 //=======================================================================
168 Standard_Integer bopfuse(Draw_Interpretor& di, Standard_Integer n, const char** a)
169 {
170   return bopsmt(di, n, a, BOPAlgo_FUSE);
171 }
172 //=======================================================================
173 //function : bopcut
174 //purpose  : 
175 //=======================================================================
176 Standard_Integer bopcut(Draw_Interpretor& di, Standard_Integer n, const char** a)
177 {
178   return bopsmt(di, n, a, BOPAlgo_CUT);
179 }
180 //=======================================================================
181 //function : boptuc
182 //purpose  : 
183 //=======================================================================
184 Standard_Integer boptuc(Draw_Interpretor& di, Standard_Integer n, const char** a)
185 {
186   return bopsmt(di, n, a, BOPAlgo_CUT21);
187 }
188 //=======================================================================
189 //function : bopsection
190 //purpose  : 
191 //=======================================================================
192 Standard_Integer bopsection(Draw_Interpretor& di, Standard_Integer n, const char** a)
193 {
194   return bopsmt(di, n, a, BOPAlgo_SECTION);
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 : bcommon
258 //purpose  : 
259 //=======================================================================
260 Standard_Integer bcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
261 {
262   return bsmt(di, n, a, BOPAlgo_COMMON);
263 }
264 //=======================================================================
265 //function : bfuse
266 //purpose  : 
267 //=======================================================================
268 Standard_Integer bfuse (Draw_Interpretor& di, Standard_Integer n, const char** a)
269 {
270   return bsmt(di, n, a, BOPAlgo_FUSE);
271 }
272 //=======================================================================
273 //function : bcut
274 //purpose  : 
275 //=======================================================================
276 Standard_Integer bcut (Draw_Interpretor& di, Standard_Integer n, const char** a)
277 {
278   return bsmt(di, n, a, BOPAlgo_CUT);
279 }
280 //=======================================================================
281 //function : btuc
282 //purpose  : 
283 //=======================================================================
284 Standard_Integer btuc (Draw_Interpretor& di, Standard_Integer n, const char** a)
285 {
286   return bsmt(di, n, a, BOPAlgo_CUT21);
287 }
288 //=======================================================================
289 //function : bsection
290 //purpose  : 
291 //=======================================================================
292 Standard_Integer  bsection(Draw_Interpretor& di, 
293                            Standard_Integer n, 
294                            const char** a)
295 {
296   const char* usage = " Usage: bsection Result s1 s2 [-n2d/-n2d1/-n2d2] [-na]\n";
297   if (n < 4) {
298     di << usage;
299     return 1;
300   }
301
302   TopoDS_Shape aS1 = DBRep::Get(a[2]);
303   TopoDS_Shape aS2 = DBRep::Get(a[3]);
304   
305   if (aS1.IsNull() || aS2.IsNull()) {
306     di << " Null shapes are not allowed \n";
307     return 1;
308   }
309
310   Standard_Boolean bApp, bPC1, bPC2;
311   //
312   bApp = Standard_True;
313   bPC1 = Standard_True;
314   bPC2 = Standard_True;
315   
316   Standard_Boolean isbadparameter = Standard_False;
317   
318   if(n > 4) {
319     const char* key1 = a[4];
320     const char* key2 = (n > 5) ? a[5] : NULL;
321     const char* pcurveconf = NULL;
322
323     if (key1 && (!strcasecmp(key1,"-n2d") || !strcasecmp(key1,"-n2d1") || !strcasecmp(key1,"-n2d2"))) {
324       pcurveconf = key1;
325     }
326     else {
327       if (!strcasecmp(key1,"-na")) {
328         bApp = Standard_False;
329       }
330       else {
331         isbadparameter = Standard_True;
332       }
333     }
334     if (key2) {
335       if(!strcasecmp(key2,"-na")) {
336         bApp = Standard_False;
337       }
338       else {
339         isbadparameter = Standard_True;
340       }
341     }
342
343     if(!isbadparameter && pcurveconf) {      
344       if (!strcasecmp(pcurveconf, "-n2d1")) {
345         bPC1 = Standard_False;
346       }
347       else {
348         if (!strcasecmp(pcurveconf, "-n2d2")) {
349           bPC2 = Standard_False;
350         }
351         else {
352           if (!strcasecmp(pcurveconf, "-n2d")) {
353             bPC1 = Standard_False;
354             bPC2 = Standard_False;
355           }
356         }
357       }
358     }
359   }
360       
361   if(!isbadparameter) {
362     Standard_Integer iErr;
363     char buf[80];
364     //
365     BRepAlgoAPI_Section aSec(aS1, aS2, Standard_False);
366     aSec.Approximation(bApp);
367     aSec.ComputePCurveOn1(bPC1);
368     aSec.ComputePCurveOn2(bPC2);
369     //
370     aSec.Build();
371     iErr=aSec.ErrorStatus();
372     if (!aSec.IsDone()) {
373       Sprintf(buf, " ErrorStatus : %d\n",  iErr);
374       di << buf;
375       return 0;
376     }
377     //
378     const TopoDS_Shape& aR=aSec.Shape();
379     if (aR.IsNull()) {
380       di << " null shape\n";
381       return 0;
382     }
383     DBRep::Set(a[1], aR);
384     return 0;
385   }
386   else {
387     di << usage;
388     return 1;
389   }
390 }
391 //=======================================================================
392 //function : bsmt
393 //purpose  : 
394 //=======================================================================
395 Standard_Integer bsmt (Draw_Interpretor& di, 
396                        Standard_Integer n, 
397                        const char** a,
398                        const BOPAlgo_Operation aOp)
399 {
400   char buf[32];
401   Standard_Integer iErr;
402   TopoDS_Shape aS1, aS2;
403   BOPCol_ListOfShape aLC;
404   //
405   if (n!=4) {
406     di << " use bx r s1 s2\n";
407     return 1;
408   }
409   //
410   aS1=DBRep::Get(a[2]);
411   aS2=DBRep::Get(a[3]);
412   //
413   if (aS1.IsNull() || aS2.IsNull()) {
414     di << " null shapes are not allowed \n";
415     return 1;
416   }
417   aLC.Append(aS1);
418   aLC.Append(aS2);
419   //
420   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
421   BOPAlgo_PaveFiller aPF(aAL);
422   //
423   aPF.SetArguments(aLC);
424   //
425   aPF.Perform();
426   iErr=aPF.ErrorStatus();
427   if (iErr) {
428     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
429     di << buf;
430     return 0;
431   }
432   //
433   BRepAlgoAPI_BooleanOperation* pBuilder=NULL;
434   // 
435   if (aOp==BOPAlgo_COMMON) {
436     pBuilder=new BRepAlgoAPI_Common(aS1, aS2, aPF);
437   }
438   else if (aOp==BOPAlgo_FUSE) {
439     pBuilder=new BRepAlgoAPI_Fuse(aS1, aS2, aPF);
440   }
441   else if (aOp==BOPAlgo_CUT) {
442     pBuilder=new BRepAlgoAPI_Cut (aS1, aS2, aPF);
443   }
444   else if (aOp==BOPAlgo_CUT21) {
445     pBuilder=new BRepAlgoAPI_Cut(aS1, aS2, aPF, Standard_False);
446   }
447   //
448   iErr = pBuilder->ErrorStatus();
449   if (!pBuilder->IsDone()) {
450     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
451     di << buf;
452     return 0;
453   }
454   const TopoDS_Shape& aR=pBuilder->Shape();
455   if (aR.IsNull()) {
456     di << " null shape\n";
457     return 0;
458   }
459   DBRep::Set(a[1], aR);
460   return 0;
461 }
462
463 //=======================================================================
464 //function : bopnews
465 //purpose  : 
466 //=======================================================================
467 Standard_Integer bopnews (Draw_Interpretor& di, 
468                           Standard_Integer n, 
469                           const char** a)
470 {
471   if (n!=2) {
472     di << " use bopnews -v[e,f]\n";
473     return 0;
474   }
475   //
476   if (pPF==NULL) {
477     di << " Prepare BOPAlgo_PaveFiller first >bop S1 S2\n";
478     return 0;
479   }
480   //
481   char buf[32];
482   Standard_CString aText;
483   Standard_Integer i, i1, i2, iFound;
484   Draw_Color aTextColor(Draw_cyan);
485   TopAbs_ShapeEnum aT;
486   Handle(BOPTest_DrawableShape) aDShape;
487   //
488   const BOPDS_PDS& pDS=pPF->PDS();
489   //
490   aT=TopAbs_SHAPE;
491   if (!strcmp (a[1], "-f")) {
492     aT=TopAbs_FACE;
493   }
494   else if (!strcmp (a[1], "-e")){
495     aT=TopAbs_EDGE;
496   }
497   else if (!strcmp (a[1], "-v")){
498     aT=TopAbs_VERTEX;
499   }
500   else {
501     di << " use bopnews -v[e,f]\n";
502     return 0;
503   }
504   //
505   iFound=0;
506   i1=pDS->NbSourceShapes();
507   i2=pDS->NbShapes();
508   for (i=i1; i<i2; ++i) {
509     const BOPDS_ShapeInfo& aSI=pDS->ShapeInfo(i);
510     if (aSI.ShapeType()==aT) {
511       const TopoDS_Shape& aS=aSI.Shape();
512       //
513       Sprintf (buf, "z%d", i);
514       aText=buf;
515       aDShape=new BOPTest_DrawableShape (aS, aText, aTextColor);
516       Draw::Set (aText, aDShape);
517       //
518       Sprintf (buf, " z%d", i);
519       di << buf;
520       //
521       iFound=1;
522     }
523   }
524   //
525   if (iFound) {
526     di << "\n";
527   }
528   else {
529     di << " not found\n";
530   }
531   //
532   return 0;
533 }
534
535 //=======================================================================
536 //function : bopcurves
537 //purpose  : 
538 //=======================================================================
539 Standard_Integer bopcurves (Draw_Interpretor& di, 
540                             Standard_Integer n, 
541                             const char** a)
542 {
543   if (n<3) {
544     di << " use bopcurves F1 F2 [-2d]\n";
545     return 1;
546   }
547
548   TopoDS_Shape S1 = DBRep::Get(a[1]);
549   TopoDS_Shape S2 = DBRep::Get(a[2]);
550   TopAbs_ShapeEnum aType;
551
552   if (S1.IsNull() || S2.IsNull()) {
553     di << " Null shapes is not allowed \n";
554     return 1;
555   }
556
557   aType=S1.ShapeType();
558   if (aType != TopAbs_FACE) {
559     di << " Type mismatch F1\n";
560     return 1;
561   }
562   aType=S2.ShapeType();
563   if (aType != TopAbs_FACE) {
564     di << " Type mismatch F2\n";
565     return 1;
566   }
567
568
569   const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
570   const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
571
572   Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone, bMake2dCurves;
573   Standard_Integer i, aNbCurves;
574   Standard_Real anAppTol, aTolR;
575   TCollection_AsciiString aNm("c_");
576
577   bMake2dCurves = Standard_False;
578   if (n > 3) {
579     if (!strcasecmp(a[3],"-2d")) {
580       bMake2dCurves = Standard_True;
581     } else {
582       di << "Wrong key. To build 2d curves use: bopcurves F1 F2 -2d \n";
583       return 1;
584     }
585   }
586   //
587
588   aToApproxC3d = Standard_True;
589   aToApproxC2dOnS1 = bMake2dCurves;
590   aToApproxC2dOnS2 = bMake2dCurves;
591   anAppTol=0.0000001;
592
593
594   IntTools_FaceFace aFF;
595   
596   aFF.SetParameters (aToApproxC3d,
597                      aToApproxC2dOnS1,
598                      aToApproxC2dOnS2,
599                      anAppTol);
600   
601   aFF.Perform (aF1, aF2);
602   
603   anIsDone=aFF.IsDone();
604   if (!anIsDone) {
605     di << " anIsDone=" << (Standard_Integer) anIsDone << "\n";
606     return 1;
607   }
608
609   aFF.PrepareLines3D(Standard_False);
610   const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
611
612   //
613   aTolR=aFF.TolReached3d();
614   di << "Tolerance Reached=" << aTolR << "\n";
615
616   aNbCurves=aSCs.Length();
617   if (!aNbCurves) {
618     di << " has no 3d curve\n";
619     return 1;
620   }
621   else
622   {
623     di << aNbCurves << " curve(s) found.\n";
624   }
625
626   for (i=1; i<=aNbCurves; i++) {
627     const IntTools_Curve& anIC=aSCs(i);
628
629     Handle (Geom_Curve)  aC3D = anIC.Curve();
630
631     if (aC3D.IsNull()) {
632       di << " has Null 3d curve# " << i << "\n";
633       continue;
634     }
635
636     TCollection_AsciiString anIndx(i), aNmx;
637     aNmx = aNm + anIndx;
638
639     Standard_CString nameC = aNmx.ToCString();
640
641     DrawTrSurf::Set(nameC, aC3D);
642     di << nameC << " ";
643     //
644     if (bMake2dCurves) {
645       Handle(Geom2d_Curve) aPC1 = anIC.FirstCurve2d();
646       Handle(Geom2d_Curve) aPC2 = anIC.SecondCurve2d();
647       //
648       if (aPC1.IsNull() && aPC2.IsNull()) {
649         di << " \n has Null 2d curves# " << i << "\n";
650         continue;
651       }
652       //
653       if (aPC1.IsNull()) {
654         TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
655         pc2Nx = pc2N + anIndx;
656         Standard_CString nameC2d2 = pc2Nx.ToCString();
657         //
658         DrawTrSurf::Set(nameC2d2, aPC2);
659         di << "(" << nameC2d2 << ") ";
660         di << " \n Null first 2d curve of the curve #" << i << "\n";
661         continue;
662       } else {
663         TCollection_AsciiString pc1N("c2d1_"), pc1Nx;
664         pc1Nx = pc1N + anIndx;
665         Standard_CString nameC2d1 = pc1Nx.ToCString();
666         //
667         DrawTrSurf::Set(nameC2d1, aPC1);
668         di << "(" << nameC2d1;
669       }
670       //
671       if (aPC2.IsNull()) {
672         di << ") \n Null second 2d curve of the curve #" << i << "\n";
673         continue;
674       } else {
675         TCollection_AsciiString pc2N("c2d2_"), pc2Nx;
676         pc2Nx = pc2N + anIndx;
677         Standard_CString nameC2d2 = pc2Nx.ToCString();
678         //
679         DrawTrSurf::Set(nameC2d2, aPC2);
680         di << ", " << nameC2d2 << ") ";
681       }
682     }
683   }
684
685   di << "\n";
686   
687   return 0;
688 }