0023882: Memory leak is reported on BOP in test bugs fclasses bug7287_5.
[occt.git] / src / BOPTest / BOPTest_BOPCommands.cxx
1 // Created on: 2000-03-16
2 // Created by: Peter KURNEV
3 // Copyright (c) 2000-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <BOPTest.ixx>
22
23 #include <stdio.h>
24
25 #include <DBRep.hxx>
26
27 #include <NCollection_BaseAllocator.hxx>
28 #include <NCollection_IncAllocator.hxx>
29
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <BRep_Builder.hxx>
33
34 #include <BOPAlgo_PaveFiller.hxx>
35 #include <BOPAlgo_Operation.hxx>
36 #include <BOPAlgo_BOP.hxx>
37 #include <BOPDS_DS.hxx>
38 #include <BOPTest_DrawableShape.hxx>
39 #include <BOPCol_ListOfShape.hxx>
40
41 #include <TCollection_AsciiString.hxx>
42 #include <IntTools_FaceFace.hxx>
43 #include <IntTools_Curve.hxx>
44 #include <DrawTrSurf.hxx>
45 #include <Draw_Color.hxx>
46 #include <Draw.hxx>
47 #include <BRepAlgoAPI_BooleanOperation.hxx>
48 #include <BRepAlgoAPI_Common.hxx>
49 #include <BRepAlgoAPI_Fuse.hxx>
50 #include <BRepAlgoAPI_Cut.hxx>
51 #include <BRepAlgoAPI_Section.hxx>
52
53 //
54 static BOPAlgo_PaveFiller* pPF=NULL;
55 //
56
57 static
58   Standard_Integer bopsmt(Draw_Interpretor& di,
59                           Standard_Integer n,
60                           const char** a,
61                           const BOPAlgo_Operation aOp);
62 static
63   Standard_Integer bsmt (Draw_Interpretor& di, 
64                        Standard_Integer n, 
65                        const char** a,
66                        const BOPAlgo_Operation aOp);
67 //
68 static Standard_Integer bop       (Draw_Interpretor&, Standard_Integer, const char**);
69 static Standard_Integer bopsection(Draw_Interpretor&, Standard_Integer, const char**);
70 static Standard_Integer boptuc    (Draw_Interpretor&, Standard_Integer, const char**);
71 static Standard_Integer bopcut    (Draw_Interpretor&, Standard_Integer, const char**);
72 static Standard_Integer bopfuse   (Draw_Interpretor&, Standard_Integer, const char**);
73 static Standard_Integer bopcommon (Draw_Interpretor&, Standard_Integer, const char**);
74 //
75 static Standard_Integer bsection  (Draw_Interpretor&, Standard_Integer, const char**);
76 static Standard_Integer btuc      (Draw_Interpretor&, Standard_Integer, const char**);
77 static Standard_Integer bcut      (Draw_Interpretor&, Standard_Integer, const char**);
78 static Standard_Integer bfuse     (Draw_Interpretor&, Standard_Integer, const char**);
79 static Standard_Integer bcommon   (Draw_Interpretor&, Standard_Integer, const char**);
80 //
81 static Standard_Integer bopcurves (Draw_Interpretor&, Standard_Integer, const char**);
82 static Standard_Integer bopnews   (Draw_Interpretor&, Standard_Integer, const char**);
83
84 //=======================================================================
85 //function : BOPCommands
86 //purpose  : 
87 //=======================================================================
88   void BOPTest::BOPCommands(Draw_Interpretor& theCommands)
89 {
90   static Standard_Boolean done = Standard_False;
91   if (done) return;
92   done = Standard_True;
93   // Chapter's name
94   const char* g = "BOP commands";
95   // Commands
96   
97   theCommands.Add("bop"       , "use bop s1 s2"   , __FILE__, bop, g);
98   theCommands.Add("bopcommon" , "use bopcommon r" , __FILE__, bopcommon, g);
99   theCommands.Add("bopfuse"   , "use bopfuse r"   , __FILE__,bopfuse, g);
100   theCommands.Add("bopcut"    , "use bopcut"      , __FILE__,bopcut, g);
101   theCommands.Add("boptuc"    , "use boptuc"      , __FILE__,boptuc, g);
102   theCommands.Add("bopsection", "use bopsection"  , __FILE__,bopsection, g);
103   //
104   theCommands.Add("bcommon" , "use bcommon r s1 s2" , __FILE__,bcommon, g);
105   theCommands.Add("bfuse"   , "use bfuse r s1 s2"   , __FILE__,bfuse, g);
106   theCommands.Add("bcut"    , "use bcut r s1 s2"    , __FILE__,bcut, g);
107   theCommands.Add("btuc"    , "use btuc r s1 s2"    , __FILE__,btuc, g);
108   theCommands.Add("bsection", "Use >bsection r s1 s2 [-n2d/-n2d1/-n2d2] [-na]", 
109                                                       __FILE__, bsection, g);
110   //
111   theCommands.Add("bopcurves", "use  bopcurves F1 F2", __FILE__, bopcurves, g);
112   theCommands.Add("bopnews", "use  bopnews -v[e,f]"  , __FILE__, bopnews, g);
113 }
114
115 //=======================================================================
116 //function : bop
117 //purpose  : 
118 //=======================================================================
119 Standard_Integer bop (Draw_Interpretor& di, Standard_Integer n, const char** a)
120 {
121   char buf[32];
122   Standard_Integer iErr;
123   TopoDS_Shape aS1, aS2;
124   BOPCol_ListOfShape aLC;
125   //
126   if (n!=3) {
127     di << " use bop Shape1 Shape2\n";
128     return 1;
129   }
130   //
131   aS1=DBRep::Get(a[1]);
132   aS2=DBRep::Get(a[2]);
133   //
134   if (aS1.IsNull() || aS2.IsNull()) {
135     di << " null shapes are not allowed \n";
136     return 1;
137   }
138   //
139   aLC.Append(aS1);
140   aLC.Append(aS2);
141   //
142   if (pPF!=NULL) {
143     delete pPF;
144     pPF=NULL;
145   }
146   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
147   pPF=new BOPAlgo_PaveFiller(aAL);
148   //
149   pPF->SetArguments(aLC);
150   //
151   pPF->Perform();
152   iErr=pPF->ErrorStatus();
153   if (iErr) {
154     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
155     di << buf;
156     return 0;
157   }
158   //
159   return 0;
160 }
161 //=======================================================================
162 //function : bopcommon
163 //purpose  : 
164 //=======================================================================
165 Standard_Integer bopcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
166 {
167   return bopsmt(di, n, a, BOPAlgo_COMMON);
168 }
169 //=======================================================================
170 //function : bopfuse
171 //purpose  : 
172 //=======================================================================
173 Standard_Integer bopfuse(Draw_Interpretor& di, Standard_Integer n, const char** a)
174 {
175   return bopsmt(di, n, a, BOPAlgo_FUSE);
176 }
177 //=======================================================================
178 //function : bopcut
179 //purpose  : 
180 //=======================================================================
181 Standard_Integer bopcut(Draw_Interpretor& di, Standard_Integer n, const char** a)
182 {
183   return bopsmt(di, n, a, BOPAlgo_CUT);
184 }
185 //=======================================================================
186 //function : boptuc
187 //purpose  : 
188 //=======================================================================
189 Standard_Integer boptuc(Draw_Interpretor& di, Standard_Integer n, const char** a)
190 {
191   return bopsmt(di, n, a, BOPAlgo_CUT21);
192 }
193 //=======================================================================
194 //function : bopsection
195 //purpose  : 
196 //=======================================================================
197 Standard_Integer bopsection(Draw_Interpretor& di, Standard_Integer n, const char** a)
198 {
199   return bopsmt(di, n, a, BOPAlgo_SECTION);
200 }
201 //=======================================================================
202 //function : bopsmt
203 //purpose  : 
204 //=======================================================================
205 Standard_Integer bopsmt(Draw_Interpretor& di,
206                         Standard_Integer n,
207                         const char** a,
208                         const BOPAlgo_Operation aOp)
209 {
210   if (n<2) {
211     di << " use bopsmt r\n";
212     return 0;
213   }
214   //
215   if (!pPF) {
216     di << " prepare PaveFiller first\n";
217     return 0;
218   }
219   //
220   if (pPF->ErrorStatus()) {
221     di << " PaveFiller has not been done\n";
222     return 0;
223   }
224   //
225   char buf[64];
226   Standard_Integer aNb, iErr;
227   BOPAlgo_BOP aBOP;
228   //
229   const BOPCol_ListOfShape& aLC=pPF->Arguments();
230   aNb=aLC.Extent();
231   if (aNb!=2) {
232     Sprintf (buf, " wrong number of arguments %s\n", aNb);
233     di << buf;
234     return 0;
235   }
236   //
237   const TopoDS_Shape& aS1=aLC.First();
238   const TopoDS_Shape& aS2=aLC.Last();
239   //
240   aBOP.AddArgument(aS1);
241   aBOP.AddTool(aS2);
242   aBOP.SetOperation(aOp);
243   //
244   aBOP.PerformWithFiller(*pPF);
245   iErr=aBOP.ErrorStatus();
246   if (iErr) {
247     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
248     di << buf;
249     return 0;
250   }
251   //
252   const TopoDS_Shape& aR=aBOP.Shape();
253   if (aR.IsNull()) {
254     di << " null shape\n";
255     return 0;
256   }
257   //
258   DBRep::Set(a[1], aR);
259   return 0;
260 }
261 //=======================================================================
262 //function : bcommon
263 //purpose  : 
264 //=======================================================================
265 Standard_Integer bcommon (Draw_Interpretor& di, Standard_Integer n, const char** a)
266 {
267   return bsmt(di, n, a, BOPAlgo_COMMON);
268 }
269 //=======================================================================
270 //function : bfuse
271 //purpose  : 
272 //=======================================================================
273 Standard_Integer bfuse (Draw_Interpretor& di, Standard_Integer n, const char** a)
274 {
275   return bsmt(di, n, a, BOPAlgo_FUSE);
276 }
277 //=======================================================================
278 //function : bcut
279 //purpose  : 
280 //=======================================================================
281 Standard_Integer bcut (Draw_Interpretor& di, Standard_Integer n, const char** a)
282 {
283   return bsmt(di, n, a, BOPAlgo_CUT);
284 }
285 //=======================================================================
286 //function : btuc
287 //purpose  : 
288 //=======================================================================
289 Standard_Integer btuc (Draw_Interpretor& di, Standard_Integer n, const char** a)
290 {
291   return bsmt(di, n, a, BOPAlgo_CUT21);
292 }
293 //=======================================================================
294 //function : bsection
295 //purpose  : 
296 //=======================================================================
297 Standard_Integer  bsection(Draw_Interpretor& di, 
298                            Standard_Integer n, 
299                            const char** a)
300 {
301   const char* usage = " Usage: bsection Result s1 s2 [-n2d/-n2d1/-n2d2] [-na]\n";
302   if (n < 4) {
303     di << usage;
304     return 1;
305   }
306
307   TopoDS_Shape aS1 = DBRep::Get(a[2]);
308   TopoDS_Shape aS2 = DBRep::Get(a[3]);
309   
310   if (aS1.IsNull() || aS2.IsNull()) {
311     di << " Null shapes are not allowed \n";
312     return 1;
313   }
314
315   Standard_Boolean bApp, bPC1, bPC2;
316   //
317   bApp = Standard_True;
318   bPC1 = Standard_True;
319   bPC2 = Standard_True;
320   
321   Standard_Boolean isbadparameter = Standard_False;
322   
323   if(n > 4) {
324     const char* key1 = a[4];
325     const char* key2 = (n > 5) ? a[5] : NULL;
326     const char* pcurveconf = NULL;
327
328 #ifdef WNT
329     if (key1 && (!strcasecmp(key1,"-n2d") || !strcasecmp(key1,"-n2d1") || !strcasecmp(key1,"-n2d2"))) {
330 #else 
331     if (key1 && (!strncasecmp(key1,"-n2d", 4) || !strncasecmp(key1,"-n2d1", 5) || !strncasecmp(key1,"-n2d2", 5))) {
332 #endif
333       pcurveconf = key1;
334     }
335     else {
336 #ifdef WNT
337       if (!strcasecmp(key1,"-na")) {
338 #else 
339       if(!strncasecmp(key1,"-na", 3)) {
340 #endif
341         bApp = Standard_False;
342       }
343       else {
344         isbadparameter = Standard_True;
345       }
346     }
347     if (key2) {
348 #ifdef WNT
349       if(!strcasecmp(key2,"-na")) {
350 #else 
351       if (!strncasecmp(key2,"-na", 3)) {
352 #endif
353         bApp = Standard_False;
354       }
355       else {
356         isbadparameter = Standard_True;
357       }
358     }
359
360     if(!isbadparameter && pcurveconf) {      
361 #ifdef WNT
362       if (!strcasecmp(pcurveconf, "-n2d1")) {
363 #else 
364       if (!strncasecmp(pcurveconf, "-n2d1", 5)) {
365 #endif
366         bPC1 = Standard_False;
367       }
368       else {
369 #ifdef WNT
370         if (!strcasecmp(pcurveconf, "-n2d2")) {
371 #else 
372         if (!strncasecmp(pcurveconf, "-n2d2", 5)) {
373 #endif
374           bPC2 = Standard_False;
375         }
376         else {
377 #ifdef WNT
378           if (!strcasecmp(pcurveconf, "-n2d")) {
379 #else 
380           if (!strncasecmp(pcurveconf, "-n2d", 4)) {
381 #endif
382             bPC1 = Standard_False;
383             bPC2 = Standard_False;
384           }
385         }
386       }
387     }
388   }
389       
390   if(!isbadparameter) {
391     Standard_Integer iErr;
392     char buf[80];
393     //
394     BRepAlgoAPI_Section aSec(aS1, aS2, Standard_False);
395     aSec.Approximation(bApp);
396     aSec.ComputePCurveOn1(bPC1);
397     aSec.ComputePCurveOn2(bPC2);
398     //
399     aSec.Build();
400     iErr=aSec.ErrorStatus();
401     if (!aSec.IsDone()) {
402       Sprintf(buf, " ErrorStatus : %d\n",  iErr);
403       di << buf;
404       return 0;
405     }
406     //
407     const TopoDS_Shape& aR=aSec.Shape();
408     if (aR.IsNull()) {
409       di << " null shape\n";
410       return 0;
411     }
412     DBRep::Set(a[1], aR);
413     return 0;
414   }
415   else {
416     di << usage;
417     return 1;
418   }
419   return 0;
420 }
421 //=======================================================================
422 //function : bsmt
423 //purpose  : 
424 //=======================================================================
425 Standard_Integer bsmt (Draw_Interpretor& di, 
426                        Standard_Integer n, 
427                        const char** a,
428                        const BOPAlgo_Operation aOp)
429 {
430   char buf[32];
431   Standard_Integer iErr;
432   TopoDS_Shape aS1, aS2;
433   BOPCol_ListOfShape aLC;
434   //
435   if (n!=4) {
436     di << " use bx r s1 s2\n";
437     return 1;
438   }
439   //
440   aS1=DBRep::Get(a[2]);
441   aS2=DBRep::Get(a[3]);
442   //
443   if (aS1.IsNull() || aS2.IsNull()) {
444     di << " null shapes are not allowed \n";
445     return 1;
446   }
447   aLC.Append(aS1);
448   aLC.Append(aS2);
449   //
450   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
451   BOPAlgo_PaveFiller aPF(aAL);
452   //
453   aPF.SetArguments(aLC);
454   //
455   aPF.Perform();
456   iErr=aPF.ErrorStatus();
457   if (iErr) {
458     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
459     di << buf;
460     return 0;
461   }
462   //
463   BRepAlgoAPI_BooleanOperation* pBuilder=NULL;
464   // 
465   if (aOp==BOPAlgo_COMMON) {
466     pBuilder=new BRepAlgoAPI_Common(aS1, aS2, aPF);
467   }
468   else if (aOp==BOPAlgo_FUSE) {
469     pBuilder=new BRepAlgoAPI_Fuse(aS1, aS2, aPF);
470   }
471   else if (aOp==BOPAlgo_CUT) {
472     pBuilder=new BRepAlgoAPI_Cut (aS1, aS2, aPF);
473   }
474   else if (aOp==BOPAlgo_CUT21) {
475     pBuilder=new BRepAlgoAPI_Cut(aS1, aS2, aPF, Standard_False);
476   }
477   //
478   iErr = pBuilder->ErrorStatus();
479   if (!pBuilder->IsDone()) {
480     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
481     di << buf;
482     return 0;
483   }
484   const TopoDS_Shape& aR=pBuilder->Shape();
485   if (aR.IsNull()) {
486     di << " null shape\n";
487     return 0;
488   }
489   DBRep::Set(a[1], aR);
490   return 0;
491 }
492
493 //=======================================================================
494 //function : bopnews
495 //purpose  : 
496 //=======================================================================
497 Standard_Integer bopnews (Draw_Interpretor& di, 
498                           Standard_Integer n, 
499                           const char** a)
500 {
501   if (n!=2) {
502     di << " use bopnews -v[e,f]\n";
503     return 0;
504   }
505   //
506   if (pPF==NULL) {
507     di << " Prepare BOPAlgo_PaveFiller first >bop S1 S2\n";
508     return 0;
509   }
510   //
511   char buf[32];
512   Standard_CString aText;
513   Standard_Integer i, i1, i2, iFound;
514   Draw_Color aTextColor(Draw_cyan);
515   TopAbs_ShapeEnum aT;
516   Handle(BOPTest_DrawableShape) aDShape;
517   //
518   const BOPDS_PDS& pDS=pPF->PDS();
519   //
520   aT=TopAbs_SHAPE;
521   if (!strcmp (a[1], "-f")) {
522     aT=TopAbs_FACE;
523   }
524   else if (!strcmp (a[1], "-e")){
525     aT=TopAbs_EDGE;
526   }
527   else if (!strcmp (a[1], "-v")){
528     aT=TopAbs_VERTEX;
529   }
530   else {
531     di << " use bopnews -v[e,f]\n";
532     return 0;
533   }
534   //
535   iFound=0;
536   i1=pDS->NbSourceShapes();
537   i2=pDS->NbShapes();
538   for (i=i1; i<i2; ++i) {
539     const BOPDS_ShapeInfo& aSI=pDS->ShapeInfo(i);
540     if (aSI.ShapeType()==aT) {
541       const TopoDS_Shape& aS=aSI.Shape();
542       //
543       Sprintf (buf, "z%d", i);
544       aText=buf;
545       aDShape=new BOPTest_DrawableShape (aS, aText, aTextColor);
546       Draw::Set (aText, aDShape);
547       //
548       Sprintf (buf, " z%d", i);
549       di << buf;
550       //
551       iFound=1;
552     }
553   }
554   //
555   if (iFound) {
556     di << "\n";
557   }
558   else {
559     di << " not found\n";
560   }
561   //
562   return 0;
563 }
564
565 //=======================================================================
566 //function : bopcurves
567 //purpose  : 
568 //=======================================================================
569 Standard_Integer bopcurves (Draw_Interpretor& di, 
570                             Standard_Integer n, 
571                             const char** a)
572 {
573   if (n<3) {
574     di << " use bopcurves F1 F2\n";
575     return 1;
576   }
577
578   TopoDS_Shape S1 = DBRep::Get(a[1]);
579   TopoDS_Shape S2 = DBRep::Get(a[2]);
580   TopAbs_ShapeEnum aType;
581
582   if (S1.IsNull() || S2.IsNull()) {
583     di << " Null shapes is not allowed \n";
584     return 1;
585   }
586
587   aType=S1.ShapeType();
588   if (aType != TopAbs_FACE) {
589     di << " Type mismatch F1\n";
590     return 1;
591   }
592   aType=S2.ShapeType();
593   if (aType != TopAbs_FACE) {
594     di << " Type mismatch F2\n";
595     return 1;
596   }
597
598
599   const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
600   const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
601
602   Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone;
603   Standard_Integer i, aNbCurves;
604   Standard_Real anAppTol, aTolR;
605   TCollection_AsciiString aNm("c_");
606
607   aToApproxC3d=Standard_True;
608   aToApproxC2dOnS1=Standard_False;
609   aToApproxC2dOnS2=Standard_False;
610   anAppTol=0.0000001;
611
612
613   IntTools_FaceFace aFF;
614   
615   aFF.SetParameters (aToApproxC3d,
616                      aToApproxC2dOnS1,
617                      aToApproxC2dOnS2,
618                      anAppTol);
619   
620   aFF.Perform (aF1, aF2);
621   
622   anIsDone=aFF.IsDone();
623   if (!anIsDone) {
624     di << " anIsDone=" << (Standard_Integer) anIsDone << "\n";
625     return 1;
626   }
627
628   aFF.PrepareLines3D();
629   const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
630
631   //
632   aTolR=aFF.TolReached3d();
633   di << "Tolerance Reached=" << aTolR << "\n";
634
635   aNbCurves=aSCs.Length();
636   if (!aNbCurves) {
637     di << " has no 3d curve\n";
638     return 1;
639   }
640
641   for (i=1; i<=aNbCurves; i++) {
642     const IntTools_Curve& anIC=aSCs(i);
643
644     Handle (Geom_Curve) aC3D=anIC.Curve();
645
646     if (aC3D.IsNull()) {
647       di << " has Null 3d curve# " << i << "%d\n";
648       continue;
649     }
650
651     TCollection_AsciiString anIndx(i), aNmx;
652     aNmx=aNm+anIndx;
653     Standard_CString name= aNmx.ToCString();
654     DrawTrSurf::Set(name, aC3D);
655     di << name << " ";
656   }
657
658   di << "\n";
659   
660   return 0;
661 }