0031172: Unexpected result of BRepTools::OuterWire()
[occt.git] / src / GeomliteTest / GeomliteTest_API2dCommands.cxx
1 // Created on: 1995-01-11
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // modified : pmn 11/04/97 : mis dans GeomliteTest
18
19
20 #include <GeomliteTest.hxx>
21 #include <Geom2d_BSplineCurve.hxx>
22 #include <Draw.hxx>
23 #include <Draw_Interpretor.hxx>
24 #include <DrawTrSurf.hxx>
25 #include <Draw_Appli.hxx>
26 #include <DrawTrSurf_Curve2d.hxx>
27 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
28 #include <Geom2dAPI_ExtremaCurveCurve.hxx>
29 #include <Geom2dAPI_Interpolate.hxx>
30 #include <Geom2dAPI_PointsToBSpline.hxx>
31 #include <Geom2dAPI_InterCurveCurve.hxx>
32 #include <Geom2d_Line.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <TColgp_Array1OfPnt2d.hxx>
35 #include <gp_Pnt.hxx>
36 #include <Draw_Marker2D.hxx>
37 #include <Draw_Color.hxx>
38 #include <Draw_MarkerShape.hxx>
39 #include <TColStd_Array1OfReal.hxx>
40 #include <GeomAbs_Shape.hxx>
41 #include <Precision.hxx>
42 #include <Geom2d_Circle.hxx>
43 #include <IntAna2d_AnaIntersection.hxx>
44 #include <IntAna2d_IntPoint.hxx>
45 #include <IntAna2d_Conic.hxx>
46 #include <IntRes2d_IntersectionPoint.hxx>
47 #include <Geom2dAdaptor_GHCurve.hxx>
48 #include <Message.hxx>
49
50 #include <memory>
51 #include <stdio.h>
52 #ifdef _WIN32
53 Standard_IMPORT Draw_Viewer dout;
54 #endif
55
56 //=======================================================================
57 //function : proj
58 //purpose  : 
59 //=======================================================================
60
61 static Standard_Integer proj (Draw_Interpretor& di, Standard_Integer n, const char** a)
62 {
63   if ( n < 4) return 1;
64
65   gp_Pnt2d P(Draw::Atof(a[2]),Draw::Atof(a[3]));
66
67   char name[100];
68
69   Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[1]);
70
71   if (GC.IsNull())
72     return 1;
73
74   Geom2dAPI_ProjectPointOnCurve proj(P,GC,GC->FirstParameter(),
75                                           GC->LastParameter());
76   
77   for (Standard_Integer i = 1; i <= proj.NbPoints(); i++)
78   {
79     gp_Pnt2d aP1 = proj.Point(i);
80     const Standard_Real aDist = P.Distance(aP1);
81     Sprintf(name, "%s%d", "ext_", i);
82
83     if (aDist > Precision::PConfusion())
84     {
85       Handle(Geom2d_Line) L = new Geom2d_Line(P, gp_Dir2d(aP1.XY() - P.XY()));
86       Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., aDist);
87       DrawTrSurf::Set(name, CT);
88     }
89     else
90     {
91       DrawTrSurf::Set(name, aP1);
92     }
93
94     di << name << " ";
95   }
96
97   return 0;
98 }
99
100 //=======================================================================
101 //function : appro
102 //purpose  : 
103 //=======================================================================
104
105 static Standard_Integer appro(Draw_Interpretor& di, Standard_Integer n, const char** a)
106 {
107   // Approximation et interpolation 2d
108
109   // 2dappro
110   //     - affiche la tolerance
111   // 2dappro tol
112   //     - change la tolerance
113   // 2dappro result nbpoint 
114   //     - saisie interactive
115   // 2dappro result nbpoint curve 
116   //     - calcule des points sur la courbe
117   // 2dappro result nbpoint x1 y1 x2 y2 .. 
118   //     - tableau de points
119   // 2dappro result nbpoint x1 dx y1 y2 ..
120   //     - tableau de points (x1,y1) (x1+dx,y2) ... avec x = t
121   
122
123   static Standard_Real Tol2d = 1.e-6;
124
125   if (n < 3) {
126     if (n == 2) 
127       Tol2d = Draw::Atof(a[1]);
128     
129     di << "Tolerance for 2d approx : "<< Tol2d << "\n";
130     return 0;
131   }
132
133
134   Standard_Integer i, Nb = Draw::Atoi(a[2]);
135   
136   Standard_Boolean hasPoints = Standard_True;
137   TColgp_Array1OfPnt2d Points(1, Nb);
138   TColStd_Array1OfReal YValues(1,Nb);
139   Standard_Real X0=0,DX=0;
140   
141   Handle(Draw_Marker2D) mark;
142   
143   if (n == 3)  {
144     // saisie interactive
145     Standard_Integer id,XX,YY,b;
146     dout.Select(id,XX,YY,b);
147     Standard_Real zoom = dout.Zoom(id);
148
149     Points(1) = gp_Pnt2d( ((Standard_Real)XX)/zoom, 
150                           ((Standard_Real)YY)/zoom );
151     
152     mark = new Draw_Marker2D( Points(1), Draw_X, Draw_vert); 
153     
154     dout << mark;
155     
156     for (i = 2; i<=Nb; i++) {
157       dout.Select(id,XX,YY,b);
158       Points(i) = gp_Pnt2d( ((Standard_Real)XX)/zoom, 
159                             ((Standard_Real)YY)/zoom );
160       mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert); 
161       dout << mark;
162     }
163   }    
164   else {
165     if ( n == 4) {
166     // points sur courbe
167       Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[3]);
168       if ( GC.IsNull()) 
169         return 1;
170
171       Standard_Real U, U1, U2;
172       U1 = GC->FirstParameter();
173       U2 = GC->LastParameter();
174       Standard_Real Delta = ( U2 - U1) / (Nb-1);
175       for ( i = 1 ; i <= Nb; i++) {
176         U = U1 + (i-1) * Delta;
177         Points(i) = GC->Value(U);
178       }
179     }
180
181     else {
182       // test points ou ordonnees
183       Standard_Integer nc = n - 3;
184       if (nc == 2 * Nb) {
185         // points
186         nc = 3;
187         for (i = 1; i <= Nb; i++) {
188           Points(i).SetCoord(Draw::Atof(a[nc]),Draw::Atof(a[nc+1]));
189           nc += 2;
190         }
191       }
192       else if (nc - 2 == Nb) {
193         // YValues
194         hasPoints = Standard_False;
195         nc = 5;
196         X0 = Draw::Atof(a[3]);
197         DX = Draw::Atof(a[4]);
198         for (i = 1; i <= Nb; i++) {
199           YValues(i) = Draw::Atof(a[nc]);
200           Points(i).SetCoord(X0+(i-1)*DX,YValues(i));
201           nc++;
202         }
203       }
204       else
205         return 1;
206     }
207     // display the points
208     for ( i = 1 ; i <= Nb; i++) {
209       mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert); 
210       dout << mark;
211     }
212   }
213   dout.Flush();
214   Standard_Integer Dmin = 3;
215   Standard_Integer Dmax = 8;
216   
217   Handle(Geom2d_BSplineCurve) TheCurve;
218   if (hasPoints)
219   {
220     if (!strcmp (a[0], "2dinterpole"))
221     {
222       Geom2dAPI_Interpolate anInterpol (new TColgp_HArray1OfPnt2d(Points), Standard_False, Tol2d);
223       anInterpol.Perform();
224       if (!anInterpol.IsDone())
225       {
226         di << "not done";
227         return 1;
228       }
229       TheCurve = anInterpol.Curve();
230     }
231     else
232     {
233       Geom2dAPI_PointsToBSpline anApprox (Points, Dmin, Dmax, GeomAbs_C2, Tol2d);
234       if (!anApprox.IsDone())
235       {
236         di << "not done";
237         return 1;
238       }
239       TheCurve = anApprox.Curve();
240     }
241   }
242   else
243   {
244     if (!strcmp (a[0], "2dinterpole"))
245     {
246       di << "incorrect usage";
247       return 1;
248     }
249     Geom2dAPI_PointsToBSpline anApprox (YValues, X0, DX, Dmin, Dmax, GeomAbs_C2, Tol2d);
250     if (!anApprox.IsDone())
251     {
252       di << "not done";
253       return 1;
254     }
255     TheCurve = anApprox.Curve();
256   }
257   
258   DrawTrSurf::Set(a[1], TheCurve);
259   di << a[1];
260
261   return 0;
262
263 }
264
265 //=======================================================================
266 //function : extrema
267 //purpose  : 
268 //=======================================================================
269
270 static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const char** a)
271 {
272   if ( n<3) return 1;
273
274   Handle(Geom2d_Curve)   GC1, GC2;
275
276   Standard_Real U1f,U1l,U2f,U2l;
277
278   GC1 = DrawTrSurf::GetCurve2d(a[1]);
279   if ( GC1.IsNull())
280     return 1;
281   U1f = GC1->FirstParameter();
282   U1l = GC1->LastParameter();
283
284   GC2 = DrawTrSurf::GetCurve2d(a[2]);
285   if ( GC2.IsNull())
286     return 1;
287   U2f = GC2->FirstParameter();
288   U2l = GC2->LastParameter();
289
290   char name[100];
291
292   Geom2dAPI_ExtremaCurveCurve Ex(GC1,GC2,U1f,U1l,U2f,U2l);
293   Standard_Boolean isInfinitySolutions = Ex.Extrema().IsParallel();
294   const Standard_Integer aNExtr = Ex.NbExtrema();
295
296   if (aNExtr == 0 || isInfinitySolutions)
297   {
298     // Infinity solutions flag may be set with 0 number of 
299     // solutions in analytic extrema Curve/Curve.
300     if (isInfinitySolutions) 
301       di << "Infinite number of extremas, distance = " << Ex.LowerDistance() << "\n";
302     else
303       di << "No solutions!\n";
304   }
305
306   for (Standard_Integer i = 1; i <= aNExtr; i++)
307   {
308     gp_Pnt2d P1,P2;
309     Ex.Points(i,P1,P2);
310     di << "dist " << i << ": " << Ex.Distance(i) << "  ";
311     if (Ex.Distance(i) <= Precision::PConfusion())
312     {
313       Handle(Draw_Marker2D) mark = new Draw_Marker2D( P1, Draw_X, Draw_vert); 
314       dout << mark;
315       dout.Flush();
316       Sprintf(name,"%s%d","ext_",i);
317       char* temp = name;
318       DrawTrSurf::Set(temp, P1);
319       di << name << "\n";
320     }
321     else
322     {
323       Handle(Geom2d_Line) L = new Geom2d_Line(P1,gp_Vec2d(P1,P2));
324       Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., P1.Distance(P2));
325       Sprintf(name,"%s%d","ext_",i);
326       char* temp = name; // portage WNT
327       DrawTrSurf::Set(temp, CT);
328       di << name << "\n";
329     }
330   }
331
332   return 0;
333 }
334
335 //=======================================================================
336 //function : intersect
337 //purpose  : 
338 //=======================================================================
339 static Standard_Integer intersect(Draw_Interpretor& di, Standard_Integer n, const char** a)
340 {
341   if (n < 2)
342   {
343     di.PrintHelp(a[0]);
344     return 1;
345   }
346
347   Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
348   if (C1.IsNull())
349   {
350     di << "Curve " << a[1] << " is null\n";
351     return 1;
352   }
353
354   Handle(Geom2d_Curve) C2;
355   Standard_Real Tol = 0.001;
356   Standard_Boolean bPrintState = Standard_False;
357
358   // Retrieve other parameters if any
359   for (Standard_Integer i = 2; i < n; ++i)
360   {
361     if (!strcmp(a[i], "-tol"))
362     {
363       Tol = Draw::Atof(a[++i]);
364     }
365     else if (!strcmp(a[i], "-state"))
366     {
367       bPrintState = Standard_True;
368     }
369     else
370     {
371       C2 = DrawTrSurf::GetCurve2d(a[i]);
372       if (C2.IsNull())
373       {
374         di << "Curve " << a[i] << " is null\n";
375         return 1;
376       }
377     }
378   }
379
380   Geom2dAPI_InterCurveCurve Intersector;
381
382   if (!C2.IsNull())
383     // Curves intersection
384     Intersector.Init(C1, C2, Tol);
385   else
386     // Self-intersection of the curve
387     Intersector.Init(C1, Tol);
388
389   const Geom2dInt_GInter& anIntTool = Intersector.Intersector();
390   if (!anIntTool.IsDone())
391   {
392     di << "Intersection failed\n";
393     return 0;
394   }
395
396   if (anIntTool.IsEmpty())
397     return 0;
398
399   Standard_Integer aNbPoints = Intersector.NbPoints();
400   for (Standard_Integer i = 1; i <= aNbPoints; i++)
401   {
402     // API simplified result
403     gp_Pnt2d P = Intersector.Point(i);
404     di << "Intersection point " << i << " : " << P.X() << " " << P.Y() << "\n";
405     // Intersection extended results from intersection tool
406     const IntRes2d_IntersectionPoint& aPInt = anIntTool.Point(i);
407     di << "parameter on the fist: " << aPInt.ParamOnFirst();
408     di << " parameter on the second: " << aPInt.ParamOnSecond() << "\n";
409     if (bPrintState)
410     {
411       di << "Intersection type: " <<
412         (aPInt.TransitionOfFirst().IsTangent() ? "TOUCH" : "INTERSECTION") << "\n";
413     }
414     Handle(Draw_Marker2D) mark = new Draw_Marker2D(P, Draw_X, Draw_vert);
415     dout << mark;
416   }
417   dout.Flush();
418
419   Handle(Geom2d_Curve) S1, S2;
420   Handle(DrawTrSurf_Curve2d) CD;
421   Standard_Integer aNbSegments = Intersector.NbSegments();
422   for (Standard_Integer i = 1; i <= aNbSegments; i++)
423   {
424     di << "Segment #" << i << " found.\n";
425     Intersector.Segment(i,S1,S2);
426     CD = new DrawTrSurf_Curve2d(S1, Draw_bleu, 30);
427     dout << CD;
428     CD = new DrawTrSurf_Curve2d(S2, Draw_violet, 30);
429     dout << CD;
430   }
431   
432   dout.Flush();
433
434   return 0;
435 }
436
437 //=======================================================================
438 //function : intersect_ana
439 //purpose  : 
440 //=======================================================================
441
442 static Standard_Integer intersect_ana(Draw_Interpretor& di, Standard_Integer n, const char** a)
443 {
444   if (n < 2)
445   {
446     Message::SendFail() << "2dintana circle circle";
447     return 1;
448   }
449
450   Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
451   if (C1.IsNull() && !C1->IsKind(STANDARD_TYPE(Geom2d_Circle)))
452     return 1;
453
454   Handle(Geom2d_Curve) C2 = DrawTrSurf::GetCurve2d(a[2]);
455   if (C2.IsNull() && !C2->IsKind(STANDARD_TYPE(Geom2d_Circle)))
456     return 1;
457
458   Handle(Geom2d_Circle) aCir1 = Handle(Geom2d_Circle)::DownCast(C1);
459   Handle(Geom2d_Circle) aCir2 = Handle(Geom2d_Circle)::DownCast(C2);
460
461   IntAna2d_AnaIntersection Intersector(aCir1->Circ2d(), aCir2->Circ2d());
462
463   Standard_Integer i;
464
465   for (i = 1; i <= Intersector.NbPoints(); i++) {
466     gp_Pnt2d P = Intersector.Point(i).Value();
467     di << "Intersection point " << i << " : " << P.X() << " " << P.Y() << "\n";
468     di << "parameter on the fist: " << Intersector.Point(i).ParamOnFirst();
469     di << " parameter on the second: " << Intersector.Point(i).ParamOnSecond() << "\n";
470     Handle(Draw_Marker2D) mark = new Draw_Marker2D(P, Draw_X, Draw_vert);
471     dout << mark;
472   }
473   dout.Flush();
474
475   return 0;
476 }
477
478 //=======================================================================
479 //function : intconcon
480 //purpose  : 
481 //=======================================================================
482
483 static Standard_Integer intconcon(Draw_Interpretor& di, Standard_Integer n, const char** a)
484 {
485   if( n < 2) 
486   {
487     Message::SendFail() << "intconcon con1 con2";
488     return 1;
489   }
490   
491   Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
492   if (C1.IsNull())
493   {
494     Message::SendFail() << a[1] << " is Null";
495     return 1;
496   }
497
498   Handle(Geom2d_Curve) C2 = DrawTrSurf::GetCurve2d(a[2]);
499   if (C2.IsNull())
500   {
501     Message::SendFail() << a[2] << " is Null";
502     return 1;
503   }
504
505   Geom2dAdaptor_Curve AC1(C1), AC2(C2);
506   GeomAbs_CurveType T1 = AC1.GetType(), T2 = AC2.GetType();
507 #if (defined(_MSC_VER) && (_MSC_VER < 1600))
508   std::auto_ptr<IntAna2d_Conic> pCon;
509 #else
510   std::unique_ptr<IntAna2d_Conic> pCon;
511 #endif  
512   switch (T2)
513   {
514   case GeomAbs_Line:
515   {
516     pCon.reset(new IntAna2d_Conic(AC2.Line()));
517     break;
518   }
519   case GeomAbs_Circle:
520   {
521     pCon.reset(new IntAna2d_Conic(AC2.Circle()));
522     break;
523   }
524   case GeomAbs_Ellipse:
525   {
526     pCon.reset(new IntAna2d_Conic(AC2.Ellipse()));
527     break;
528   }
529   case GeomAbs_Hyperbola:
530   {
531     pCon.reset(new IntAna2d_Conic(AC2.Hyperbola()));
532     break;
533   }
534   case GeomAbs_Parabola:
535   {
536     pCon.reset(new IntAna2d_Conic(AC2.Parabola()));
537     break;
538   }
539   default:
540     Message::SendFail() << a[2] << " is not conic";
541     return 1;
542   }
543
544   IntAna2d_AnaIntersection Intersector;
545   switch (T1)
546   {
547   case GeomAbs_Line:
548     Intersector.Perform(AC1.Line(), *pCon);
549     break;
550   case GeomAbs_Circle:
551     Intersector.Perform(AC1.Circle(), *pCon);
552     break;
553   case GeomAbs_Ellipse:
554     Intersector.Perform(AC1.Ellipse(), *pCon);
555     break;
556   case GeomAbs_Hyperbola:
557     Intersector.Perform(AC1.Hyperbola(), *pCon);
558     break;
559   case GeomAbs_Parabola:
560     Intersector.Perform(AC1.Parabola(), *pCon);
561     break;
562   default:
563     Message::SendFail() << a[1] << " is not conic";
564     return 1;
565   }
566   
567   Standard_Integer i;
568   for ( i = 1; i <= Intersector.NbPoints(); i++) {
569     gp_Pnt2d P = Intersector.Point(i).Value();
570     di<<"Intersection point "<<i<<" : "<<P.X()<<" "<<P.Y()<<"\n";
571     di << "parameter on the fist: " << Intersector.Point(i).ParamOnFirst();
572     if (!Intersector.Point(i).SecondIsImplicit())
573     {
574       di << " parameter on the second: " << Intersector.Point(i).ParamOnSecond() << "\n";
575     }
576     else
577     {
578       di << "\n";
579     }
580     Handle(Draw_Marker2D) mark = new Draw_Marker2D( P, Draw_X, Draw_vert); 
581     dout << mark;
582   }
583   dout.Flush();
584
585   return 0;
586 }
587
588
589
590 void GeomliteTest::API2dCommands(Draw_Interpretor& theCommands)
591 {
592   static Standard_Boolean done = Standard_False;
593   if (done) return;
594
595   const char *g;
596
597   done = Standard_True;
598   g = "GEOMETRY curves and surfaces analysis";
599
600   theCommands.Add("2dproj", "proj curve x y",__FILE__, proj,g);
601
602   g = "GEOMETRY approximations";
603
604   theCommands.Add("2dapprox", "2dapprox result nbpoint [curve] [[x] y [x] y...]",__FILE__, 
605                   appro,g);
606   theCommands.Add("2dinterpole", "2dinterpole result nbpoint [curve] [[x] y [x] y ...]",__FILE__, 
607                   appro,g);
608
609   g = "GEOMETRY curves and surfaces analysis";
610
611   theCommands.Add("2dextrema", "extrema curve curve",__FILE__,
612                   extrema,g);
613
614   g = "GEOMETRY intersections";
615
616   theCommands.Add("2dintersect", "2dintersect curve1 [curve2] [-tol tol] [-state]\n"
617                    "Intersects the given 2d curve(s)."
618                    "If only one curve is given, it will be checked on self-intersection.\n"
619                    "Options:\n"
620                    " -tol - allows changing the intersection tolerance (default value is 1.e-3);\n"
621                    " -state - allows printing the intersection state for each point.",
622                    __FILE__, intersect, g);
623
624   theCommands.Add("2dintanalytical", "intersect circle1 and circle2 using IntAna",__FILE__,
625                   intersect_ana,g);
626   theCommands.Add("intconcon", "intersect conic curve1 and conic curve2 using IntAna", __FILE__,
627     intconcon, g);
628 }