0023471: Intersection algorithm produces overlapping intersection curves
[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 <BOPAlgo_SectionAttribute.hxx>
38 #include <BOPDS_DS.hxx>
39 #include <BOPTest_DrawableShape.hxx>
40 #include <BOPCol_ListOfShape.hxx>
41
42 #include <TCollection_AsciiString.hxx>
43 #include <IntTools_FaceFace.hxx>
44 #include <IntTools_Curve.hxx>
45 #include <DrawTrSurf.hxx>
46 #include <Draw_Color.hxx>
47 #include <Draw.hxx>
48
49 //
50 static BOPAlgo_PaveFiller* pPF=NULL;
51 //
52
53 static
54   Standard_Integer bopsmt(Draw_Interpretor& di,
55                           Standard_Integer n,
56                           const char** a,
57                           const BOPAlgo_Operation aOp);
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 bopnews   (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 = "BOP 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"      , __FILE__,bopcut, g);
97   theCommands.Add("boptuc"    , "use boptuc"      , __FILE__,boptuc, g);
98   theCommands.Add("bopsection", "use bopsection"  , __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", __FILE__, bopcurves, g);
108   theCommands.Add("bopnews", "use  bopnews -v[e,f]"  , __FILE__, bopnews, g);
109 }
110
111 //=======================================================================
112 //function : bop
113 //purpose  : 
114 //=======================================================================
115 Standard_Integer bop (Draw_Interpretor& di, Standard_Integer n, const char** a)
116 {
117   char buf[32];
118   Standard_Integer iErr;
119   TopoDS_Shape aS1, aS2;
120   BOPCol_ListOfShape aLC;
121   //
122   if (n!=3) {
123     di << " use bop Shape1 Shape2\n";
124     return 1;
125   }
126   //
127   aS1=DBRep::Get(a[1]);
128   aS2=DBRep::Get(a[2]);
129   //
130   if (aS1.IsNull() || aS2.IsNull()) {
131     di << " null shapes are not allowed \n";
132     return 1;
133   }
134   //
135   aLC.Append(aS1);
136   aLC.Append(aS2);
137   //
138   if (!pPF) {
139     delete pPF;
140     Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
141     pPF=new BOPAlgo_PaveFiller(aAL);
142   }
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   BOPAlgo_SectionAttribute aSec(Standard_True, Standard_True, Standard_True);
311   Standard_Boolean isbadparameter = Standard_False;
312   
313   if(n > 4) {
314     const char* key1 = a[4];
315     const char* key2 = (n > 5) ? a[5] : NULL;
316     const char* pcurveconf = NULL;
317     Standard_Boolean approx = Standard_True;
318
319 #ifdef WNT
320     if (key1 && (!strcasecmp(key1,"-n2d") || !strcasecmp(key1,"-n2d1") || !strcasecmp(key1,"-n2d2"))) {
321 #else 
322     if (key1 && (!strncasecmp(key1,"-n2d", 4) || !strncasecmp(key1,"-n2d1", 5) || !strncasecmp(key1,"-n2d2", 5))) {
323 #endif
324       pcurveconf = key1;
325     }
326     else {
327 #ifdef WNT
328       if (!strcasecmp(key1,"-na")) {
329 #else 
330       if(!strncasecmp(key1,"-na", 3)) {
331 #endif
332         approx = Standard_False;
333       }
334       else {
335         isbadparameter = Standard_True;
336       }
337     }
338     if (key2) {
339 #ifdef WNT
340       if(!strcasecmp(key2,"-na")) {
341 #else 
342       if (!strncasecmp(key2,"-na", 3)) {
343 #endif
344         approx = Standard_False;
345       }
346       else {
347         isbadparameter = Standard_True;
348       }
349     }
350
351     if(!isbadparameter && pcurveconf) {      
352 #ifdef WNT
353       if (!strcasecmp(pcurveconf, "-n2d1")) {
354 #else 
355       if (!strncasecmp(pcurveconf, "-n2d1", 5)) {
356 #endif
357         aSec.PCurveOnS1(Standard_False);
358       }
359       else {
360 #ifdef WNT
361         if (!strcasecmp(pcurveconf, "-n2d2")) {
362 #else 
363         if (!strncasecmp(pcurveconf, "-n2d2", 5)) {
364 #endif
365           aSec.PCurveOnS2(Standard_False);
366         }
367         else {
368 #ifdef WNT
369           if (!strcasecmp(pcurveconf, "-n2d")) {
370 #else 
371           if (!strncasecmp(pcurveconf, "-n2d", 4)) {
372 #endif
373             aSec.PCurveOnS1(Standard_False);
374             aSec.PCurveOnS2(Standard_False);
375           }
376         }
377       }
378     }
379     aSec.Approximation(approx);
380   }
381       
382   if(!isbadparameter) { 
383     BOPCol_ListOfShape aLC;
384     Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
385     Standard_Integer iErr;
386     char buf[80];
387     //
388     aLC.Append(aS1);
389     aLC.Append(aS2);
390     BOPAlgo_PaveFiller aPF(aAL);
391     aPF.SetArguments(aLC);
392     aPF.SetSectionAttribute(aSec);
393     //
394     aPF.Perform();
395     iErr=aPF.ErrorStatus();
396     if (iErr) {
397       Sprintf(buf, " ErrorStatus : %d\n",  iErr);
398       di << buf;
399       return 0;
400     }
401     //
402     BOPAlgo_BOP aBOP;
403     aBOP.AddArgument(aS1);
404     aBOP.AddTool(aS2);
405     aBOP.SetOperation(BOPAlgo_SECTION);
406     //
407     aBOP.PerformWithFiller(aPF);
408     iErr=aBOP.ErrorStatus();
409     if (iErr) {
410       Sprintf(buf, " ErrorStatus : %d\n",  iErr);
411       di << buf;
412       return 0;
413     }
414     //
415     const TopoDS_Shape& aR=aBOP.Shape();
416     if (aR.IsNull()) {
417       di << " null shape\n";
418       return 0;
419     }
420     DBRep::Set(a[1], aR);
421     return 0;
422   }
423   else {
424     di << usage;
425     return 1;
426   }
427   return 0;
428 }
429 //=======================================================================
430 //function : bsmt
431 //purpose  : 
432 //=======================================================================
433 Standard_Integer bsmt (Draw_Interpretor& di, 
434                        Standard_Integer n, 
435                        const char** a,
436                        const BOPAlgo_Operation aOp)
437 {
438   char buf[32];
439   Standard_Integer iErr;
440   TopoDS_Shape aS1, aS2;
441   BOPCol_ListOfShape aLC;
442   //
443   if (aOp==BOPAlgo_SECTION) {
444     if (n<4) {
445       di << " use bsection r s1 s2\n";
446       return 1;
447     }
448   }
449   //
450   else if (n!=4) {
451     di << " use bx r s1 s2\n";
452     return 1;
453   }
454   //
455   aS1=DBRep::Get(a[2]);
456   aS2=DBRep::Get(a[3]);
457   //
458   if (aS1.IsNull() || aS2.IsNull()) {
459     di << " null shapes are not allowed \n";
460     return 1;
461   }
462   //
463   aLC.Append(aS1);
464   aLC.Append(aS2);
465   //
466   Handle(NCollection_BaseAllocator)aAL=new NCollection_IncAllocator;
467   BOPAlgo_PaveFiller aPF(aAL);
468   //
469   aPF.SetArguments(aLC);
470   //
471   aPF.Perform();
472   iErr=aPF.ErrorStatus();
473   if (iErr) {
474     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
475     di << buf;
476     return 0;
477   }
478   //
479   BOPAlgo_BOP aBOP;
480   //
481   aBOP.AddArgument(aS1);
482   aBOP.AddTool(aS2);
483   aBOP.SetOperation(aOp);
484   //
485   aBOP.PerformWithFiller(aPF);
486   iErr=aBOP.ErrorStatus();
487   if (iErr) {
488     Sprintf(buf, " ErrorStatus : %d\n",  iErr);
489     di << buf;
490     return 0;
491   }
492   //
493   const TopoDS_Shape& aR=aBOP.Shape();
494   if (aR.IsNull()) {
495     di << " null shape\n";
496     return 0;
497   }
498   DBRep::Set(a[1], aR);
499   return 0;
500 }
501
502 //=======================================================================
503 //function : bopnews
504 //purpose  : 
505 //=======================================================================
506 Standard_Integer bopnews (Draw_Interpretor& di, 
507                           Standard_Integer n, 
508                           const char** a)
509 {
510   if (n!=2) {
511     di << " use bopnews -v[e,f]\n";
512     return 0;
513   }
514   //
515   if (pPF==NULL) {
516     di << " Prepare BOPAlgo_PaveFiller first >bop S1 S2\n";
517     return 0;
518   }
519   //
520   char buf[32];
521   Standard_CString aText;
522   Standard_Integer i, i1, i2, iFound;
523   Draw_Color aTextColor(Draw_cyan);
524   TopAbs_ShapeEnum aT;
525   Handle(BOPTest_DrawableShape) aDShape;
526   //
527   const BOPDS_PDS& pDS=pPF->PDS();
528   //
529   aT=TopAbs_SHAPE;
530   if (!strcmp (a[1], "-f")) {
531     aT=TopAbs_FACE;
532   }
533   else if (!strcmp (a[1], "-e")){
534     aT=TopAbs_EDGE;
535   }
536   else if (!strcmp (a[1], "-v")){
537     aT=TopAbs_VERTEX;
538   }
539   else {
540     di << " use bopnews -v[e,f]\n";
541     return 0;
542   }
543   //
544   iFound=0;
545   i1=pDS->NbSourceShapes();
546   i2=pDS->NbShapes();
547   for (i=i1; i<i2; ++i) {
548     const BOPDS_ShapeInfo& aSI=pDS->ShapeInfo(i);
549     if (aSI.ShapeType()==aT) {
550       const TopoDS_Shape& aS=aSI.Shape();
551       //
552       Sprintf (buf, "z%d", i);
553       aText=buf;
554       aDShape=new BOPTest_DrawableShape (aS, aText, aTextColor);
555       Draw::Set (aText, aDShape);
556       //
557       Sprintf (buf, " z%d", i);
558       di << buf;
559       //
560       iFound=1;
561     }
562   }
563   //
564   if (iFound) {
565     di << "\n";
566   }
567   else {
568     di << " not found\n";
569   }
570   //
571   return 0;
572 }
573
574 //=======================================================================
575 //function : bopcurves
576 //purpose  : 
577 //=======================================================================
578 Standard_Integer bopcurves (Draw_Interpretor& di, 
579                             Standard_Integer n, 
580                             const char** a)
581 {
582   if (n<3) {
583     di << " use bopcurves F1 F2\n";
584     return 1;
585   }
586
587   TopoDS_Shape S1 = DBRep::Get(a[1]);
588   TopoDS_Shape S2 = DBRep::Get(a[2]);
589   TopAbs_ShapeEnum aType;
590
591   if (S1.IsNull() || S2.IsNull()) {
592     di << " Null shapes is not allowed \n";
593     return 1;
594   }
595
596   aType=S1.ShapeType();
597   if (aType != TopAbs_FACE) {
598     di << " Type mismatch F1\n";
599     return 1;
600   }
601   aType=S2.ShapeType();
602   if (aType != TopAbs_FACE) {
603     di << " Type mismatch F2\n";
604     return 1;
605   }
606
607
608   const TopoDS_Face& aF1=*(TopoDS_Face*)(&S1);
609   const TopoDS_Face& aF2=*(TopoDS_Face*)(&S2);
610
611   Standard_Boolean aToApproxC3d, aToApproxC2dOnS1, aToApproxC2dOnS2, anIsDone;
612   Standard_Integer i, aNbCurves;
613   Standard_Real anAppTol, aTolR;
614   TCollection_AsciiString aNm("c_");
615
616   aToApproxC3d=Standard_True;
617   aToApproxC2dOnS1=Standard_False;
618   aToApproxC2dOnS2=Standard_False;
619   anAppTol=0.0000001;
620
621
622   IntTools_FaceFace aFF;
623   
624   aFF.SetParameters (aToApproxC3d,
625                      aToApproxC2dOnS1,
626                      aToApproxC2dOnS2,
627                      anAppTol);
628   
629   aFF.Perform (aF1, aF2);
630   
631   anIsDone=aFF.IsDone();
632   if (!anIsDone) {
633     di << " anIsDone=" << (Standard_Integer) anIsDone << "\n";
634     return 1;
635   }
636
637   aFF.PrepareLines3D();
638   const IntTools_SequenceOfCurves& aSCs=aFF.Lines();
639
640   //
641   aTolR=aFF.TolReached3d();
642   di << "Tolerance Reached=" << aTolR << "\n";
643
644   aNbCurves=aSCs.Length();
645   if (!aNbCurves) {
646     di << " has no 3d curve\n";
647     return 1;
648   }
649
650   for (i=1; i<=aNbCurves; i++) {
651     const IntTools_Curve& anIC=aSCs(i);
652
653     Handle (Geom_Curve) aC3D=anIC.Curve();
654
655     if (aC3D.IsNull()) {
656       di << " has Null 3d curve# " << i << "%d\n";
657       continue;
658     }
659
660     TCollection_AsciiString anIndx(i), aNmx;
661     aNmx=aNm+anIndx;
662     Standard_CString name= aNmx.ToCString();
663     DrawTrSurf::Set(name, aC3D);
664     di << name << " ";
665   }
666
667   di << "\n";
668   
669   return 0;
670 }