0029176: Exception while projection 2D-point on 2D-line
[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 <IntRes2d_IntersectionPoint.hxx>
45
46 #include <stdio.h>
47 #ifdef _WIN32
48 Standard_IMPORT Draw_Viewer dout;
49 #endif
50
51 //=======================================================================
52 //function : proj
53 //purpose  : 
54 //=======================================================================
55
56 static Standard_Integer proj (Draw_Interpretor& di, Standard_Integer n, const char** a)
57 {
58   if ( n < 4) return 1;
59
60   gp_Pnt2d P(Draw::Atof(a[2]),Draw::Atof(a[3]));
61
62   char name[100];
63
64   Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[1]);
65
66   if (GC.IsNull())
67     return 1;
68
69   Geom2dAPI_ProjectPointOnCurve proj(P,GC,GC->FirstParameter(),
70                                           GC->LastParameter());
71   
72   for (Standard_Integer i = 1; i <= proj.NbPoints(); i++)
73   {
74     gp_Pnt2d aP1 = proj.Point(i);
75     const Standard_Real aDist = P.Distance(aP1);
76     Sprintf(name, "%s%d", "ext_", i);
77
78     if (aDist > Precision::PConfusion())
79     {
80       Handle(Geom2d_Line) L = new Geom2d_Line(P, gp_Dir2d(aP1.XY() - P.XY()));
81       Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., aDist);
82       DrawTrSurf::Set(name, CT);
83     }
84     else
85     {
86       DrawTrSurf::Set(name, aP1);
87     }
88
89     di << name << " ";
90   }
91
92   return 0;
93 }
94
95 //=======================================================================
96 //function : appro
97 //purpose  : 
98 //=======================================================================
99
100 static Standard_Integer appro(Draw_Interpretor& di, Standard_Integer n, const char** a)
101 {
102   // Approximation et interpolation 2d
103
104   // 2dappro
105   //     - affiche la tolerance
106   // 2dappro tol
107   //     - change la tolerance
108   // 2dappro result nbpoint 
109   //     - saisie interactive
110   // 2dappro result nbpoint curve 
111   //     - calcule des points sur la courbe
112   // 2dappro result nbpoint x1 y1 x2 y2 .. 
113   //     - tableau de points
114   // 2dappro result nbpoint x1 dx y1 y2 ..
115   //     - tableau de points (x1,y1) (x1+dx,y2) ... avec x = t
116   
117
118   static Standard_Real Tol2d = 1.e-6;
119
120   if (n < 3) {
121     if (n == 2) 
122       Tol2d = Draw::Atof(a[1]);
123     
124     di << "Tolerance for 2d approx : "<< Tol2d << "\n";
125     return 0;
126   }
127
128
129   Standard_Integer i, Nb = Draw::Atoi(a[2]);
130   
131   Standard_Boolean hasPoints = Standard_True;
132   TColgp_Array1OfPnt2d Points(1, Nb);
133   TColStd_Array1OfReal YValues(1,Nb);
134   Standard_Real X0=0,DX=0;
135   
136   Handle(Draw_Marker2D) mark;
137   
138   if (n == 3)  {
139     // saisie interactive
140     Standard_Integer id,XX,YY,b;
141     dout.Select(id,XX,YY,b);
142     Standard_Real zoom = dout.Zoom(id);
143
144     Points(1) = gp_Pnt2d( ((Standard_Real)XX)/zoom, 
145                           ((Standard_Real)YY)/zoom );
146     
147     mark = new Draw_Marker2D( Points(1), Draw_X, Draw_vert); 
148     
149     dout << mark;
150     
151     for (i = 2; i<=Nb; i++) {
152       dout.Select(id,XX,YY,b);
153       Points(i) = gp_Pnt2d( ((Standard_Real)XX)/zoom, 
154                             ((Standard_Real)YY)/zoom );
155       mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert); 
156       dout << mark;
157     }
158   }    
159   else {
160     if ( n == 4) {
161     // points sur courbe
162       Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[3]);
163       if ( GC.IsNull()) 
164         return 1;
165
166       Standard_Real U, U1, U2;
167       U1 = GC->FirstParameter();
168       U2 = GC->LastParameter();
169       Standard_Real Delta = ( U2 - U1) / (Nb-1);
170       for ( i = 1 ; i <= Nb; i++) {
171         U = U1 + (i-1) * Delta;
172         Points(i) = GC->Value(U);
173       }
174     }
175
176     else {
177       // test points ou ordonnees
178       hasPoints = Standard_False;
179       Standard_Integer nc = n - 3;
180       if (nc == 2 * Nb) {
181         // points
182         nc = 3;
183         for (i = 1; i <= Nb; i++) {
184           Points(i).SetCoord(Draw::Atof(a[nc]),Draw::Atof(a[nc+1]));
185           nc += 2;
186         }
187       }
188       else if (nc - 2 == Nb) {
189         // YValues
190         nc = 5;
191         X0 = Draw::Atof(a[3]);
192         DX = Draw::Atof(a[4]);
193         for (i = 1; i <= Nb; i++) {
194           YValues(i) = Draw::Atof(a[nc]);
195           Points(i).SetCoord(X0+(i-1)*DX,YValues(i));
196           nc++;
197         }
198       }
199       else
200         return 1;
201     }
202     // display the points
203     for ( i = 1 ; i <= Nb; i++) {
204       mark = new Draw_Marker2D( Points(i), Draw_X, Draw_vert); 
205       dout << mark;
206     }
207   }
208   dout.Flush();
209   Standard_Integer Dmin = 3;
210   Standard_Integer Dmax = 8;
211   
212   Handle(Geom2d_BSplineCurve) TheCurve;
213   if (hasPoints)
214     TheCurve = Geom2dAPI_PointsToBSpline(Points,Dmin,Dmax,GeomAbs_C2,Tol2d);
215   else
216     TheCurve = Geom2dAPI_PointsToBSpline(YValues,X0,DX,Dmin,Dmax,GeomAbs_C2,Tol2d);
217   
218   DrawTrSurf::Set(a[1], TheCurve);
219   di << a[1];
220
221   return 0;
222
223 }
224
225 //=======================================================================
226 //function : extrema
227 //purpose  : 
228 //=======================================================================
229
230 static Standard_Integer extrema(Draw_Interpretor& di, Standard_Integer n, const char** a)
231 {
232   if ( n<3) return 1;
233
234   Handle(Geom2d_Curve)   GC1, GC2;
235
236   Standard_Real U1f,U1l,U2f,U2l;
237
238   GC1 = DrawTrSurf::GetCurve2d(a[1]);
239   if ( GC1.IsNull())
240     return 1;
241   U1f = GC1->FirstParameter();
242   U1l = GC1->LastParameter();
243
244   GC2 = DrawTrSurf::GetCurve2d(a[2]);
245   if ( GC2.IsNull())
246     return 1;
247   U2f = GC2->FirstParameter();
248   U2l = GC2->LastParameter();
249
250   char name[100];
251
252   Geom2dAPI_ExtremaCurveCurve Ex(GC1,GC2,U1f,U1l,U2f,U2l);
253   Standard_Boolean isInfinitySolutions = Ex.Extrema().IsParallel();
254   const Standard_Integer aNExtr = Ex.NbExtrema();
255
256   if (aNExtr == 0 || isInfinitySolutions)
257   {
258     // Infinity solutions flag may be set with 0 number of 
259     // solutions in analytic extrema Curve/Curve.
260     if (isInfinitySolutions) 
261       di << "Infinite number of extremas, distance = " << Ex.LowerDistance() << "\n";
262     else
263       di << "No solutions!\n";
264   }
265
266   for (Standard_Integer i = 1; i <= aNExtr; i++)
267   {
268     gp_Pnt2d P1,P2;
269     Ex.Points(i,P1,P2);
270     di << "dist " << i << ": " << Ex.Distance(i) << "  ";
271     if (Ex.Distance(i) <= Precision::PConfusion())
272     {
273       Handle(Draw_Marker2D) mark = new Draw_Marker2D( P1, Draw_X, Draw_vert); 
274       dout << mark;
275       dout.Flush();
276       Sprintf(name,"%s%d","ext_",i);
277       char* temp = name;
278       DrawTrSurf::Set(temp, P1);
279       di << name << "\n";
280     }
281     else
282     {
283       Handle(Geom2d_Line) L = new Geom2d_Line(P1,gp_Vec2d(P1,P2));
284       Handle(Geom2d_TrimmedCurve) CT = new Geom2d_TrimmedCurve(L, 0., P1.Distance(P2));
285       Sprintf(name,"%s%d","ext_",i);
286       char* temp = name; // portage WNT
287       DrawTrSurf::Set(temp, CT);
288       di << name << "\n";
289     }
290   }
291
292   return 0;
293 }
294
295 //=======================================================================
296 //function : intersect
297 //purpose  : 
298 //=======================================================================
299 static Standard_Integer intersect(Draw_Interpretor& di, Standard_Integer n, const char** a)
300 {
301   if( n < 2) 
302   {
303     cout<< "2dintersect curve curve [Tol]"<<endl;
304     return 1;
305   }
306
307   Standard_Integer k = 1;
308   Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[k++]);
309   if ( C1.IsNull()) 
310     return 1;
311
312   Standard_Real Tol = 0.001;
313   Geom2dAPI_InterCurveCurve Intersector;
314
315   Handle(Geom2d_Curve) C2;
316   if ( k < n ) {
317     C2 = DrawTrSurf::GetCurve2d(a[k++]);
318     if ( C2.IsNull())
319       return 1;
320   }
321   if(k < n)
322     Tol = Draw::Atof(a[k]);
323
324   if(!C2.IsNull())
325   {
326     Intersector.Init(C1,C2,Tol);
327   }
328   else {
329     Intersector.Init(C1, Tol);
330   }
331
332   Standard_Integer i;
333
334   for ( i = 1; i <= Intersector.NbPoints(); i++) {
335     gp_Pnt2d P = Intersector.Point(i);
336
337     di<<"Intersection point "<<i<<" : "<<P.X()<<" "<<P.Y()<<"\n";
338     di<<"parameter on the fist: "<<Intersector.Intersector().Point(i).ParamOnFirst();
339     di<<" parameter on the second: "<<Intersector.Intersector().Point(i).ParamOnSecond()<<"\n";
340     Handle(Draw_Marker2D) mark = new Draw_Marker2D( P, Draw_X, Draw_vert); 
341     dout << mark;
342   }
343   dout.Flush();
344
345   Handle(Geom2d_Curve) S1,S2;
346   Handle(DrawTrSurf_Curve2d) CD;
347   for ( i = 1; i <= Intersector.NbSegments(); i++) {
348     di << "Segment #" << i << " found.\n";
349     Intersector.Segment(i,S1,S2);
350     CD = new DrawTrSurf_Curve2d(S1, Draw_bleu, 30);
351     dout << CD;
352     CD = new DrawTrSurf_Curve2d(S2, Draw_violet, 30);
353     dout << CD;
354   }
355   
356   dout.Flush();
357
358   return 0;
359 }
360
361 //=======================================================================
362 //function : intersect
363 //purpose  : 
364 //=======================================================================
365
366 static Standard_Integer intersect_ana(Draw_Interpretor& di, Standard_Integer n, const char** a)
367 {
368   if( n < 2) 
369   {
370     cout<< "2dintana circle circle "<<endl;
371     return 1;
372   }
373   
374   Handle(Geom2d_Curve) C1 = DrawTrSurf::GetCurve2d(a[1]);
375   if ( C1.IsNull() && !C1->IsKind(STANDARD_TYPE(Geom2d_Circle))) 
376     return 1;
377
378   Handle(Geom2d_Curve) C2 = DrawTrSurf::GetCurve2d(a[2]);
379   if ( C2.IsNull() && !C2->IsKind(STANDARD_TYPE(Geom2d_Circle)))
380     return 1;
381
382   Handle(Geom2d_Circle) aCir1 = Handle(Geom2d_Circle)::DownCast(C1);
383   Handle(Geom2d_Circle) aCir2 = Handle(Geom2d_Circle)::DownCast(C2);
384
385   IntAna2d_AnaIntersection Intersector(aCir1->Circ2d(), aCir2->Circ2d());
386
387   Standard_Integer i;
388
389   for ( i = 1; i <= Intersector.NbPoints(); i++) {
390     gp_Pnt2d P = Intersector.Point(i).Value();
391     di<<"Intersection point "<<i<<" : "<<P.X()<<" "<<P.Y()<<"\n";
392         di<<"parameter on the fist: "<<Intersector.Point(i).ParamOnFirst();
393         di<<" parameter on the second: "<<Intersector.Point(i).ParamOnSecond()<<"\n";
394     Handle(Draw_Marker2D) mark = new Draw_Marker2D( P, Draw_X, Draw_vert); 
395     dout << mark;
396   }
397   dout.Flush();
398
399   return 0;
400 }
401
402
403
404 void GeomliteTest::API2dCommands(Draw_Interpretor& theCommands)
405 {
406   static Standard_Boolean done = Standard_False;
407   if (done) return;
408
409   const char *g;
410
411   done = Standard_True;
412   g = "GEOMETRY curves and surfaces analysis";
413
414   theCommands.Add("2dproj", "proj curve x y",__FILE__, proj,g);
415
416   g = "GEOMETRY approximations";
417
418   theCommands.Add("2dapprox", "2dapprox result nbpoint [curve] [[x] y [x] y...]",__FILE__, 
419                   appro,g);
420   theCommands.Add("2dinterpole", "2dinterpole result nbpoint [curve] [[x] y [x] y ...]",__FILE__, 
421                   appro,g);
422
423   g = "GEOMETRY curves and surfaces analysis";
424
425   theCommands.Add("2dextrema", "extrema curve curve",__FILE__,
426                   extrema,g);
427
428   g = "GEOMETRY intersections";
429
430   theCommands.Add("2dintersect", "intersect curve curve [Tol]",__FILE__,
431                   intersect,g);
432
433   theCommands.Add("2dintanalytical", "intersect curve curve using IntAna",__FILE__,
434                   intersect_ana,g);
435 }