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