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