0030645: Modeling Algorithms - B-spline segmentation produces wrong parametrization
[occt.git] / src / GeomliteTest / GeomliteTest_CurveCommands.cxx
1 // Created on: 1993-08-12
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-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 by xab, Tue Mar 11 18:31:18 1997
18 // Modified by PMN 14/04/97 : Passage a Geomlite
19 // Modified by JPI 01/08/97 : ajout de la commande approxcurve
20
21 #include <GeomliteTest.hxx>
22 #include <Draw_Appli.hxx>
23 #include <DrawTrSurf.hxx>
24 #include <DrawTrSurf_Curve.hxx>
25 #include <DrawTrSurf_Curve2d.hxx>
26 #include <DrawTrSurf_BezierCurve.hxx>
27 #include <DrawTrSurf_BSplineCurve.hxx>
28 #include <DrawTrSurf_BezierCurve2d.hxx>
29 #include <DrawTrSurf_BSplineCurve2d.hxx>
30 #include <Draw_Marker3D.hxx>
31 #include <Draw_Marker2D.hxx>
32 #include <Draw.hxx>
33 #include <Draw_Interpretor.hxx>
34 #include <Draw_Color.hxx>
35 #include <Draw_Display.hxx>
36
37 #include <BSplCLib.hxx>
38
39 #include <gp.hxx>
40 #include <gp_Pln.hxx>
41 #include <gp_Parab2d.hxx>
42 #include <gp_Elips2d.hxx>
43 #include <gp_Hypr2d.hxx>
44
45 #include <Geom_Line.hxx>
46 #include <Geom_Circle.hxx>
47 #include <Geom_Ellipse.hxx>
48 #include <Geom_Parabola.hxx>
49 #include <Geom_Hyperbola.hxx>
50 #include <Geom_BezierCurve.hxx>
51 #include <Geom_BSplineCurve.hxx>
52 #include <GeomAdaptor_Surface.hxx>
53 #include <GeomAdaptor_HSurface.hxx>
54
55 #include <GeomLib.hxx>
56 #include <GeomConvert.hxx>
57 #include <Geom2dConvert.hxx>
58
59 #include <Geom2d_Line.hxx>
60 #include <Geom2d_Circle.hxx>
61 #include <Geom2d_Ellipse.hxx>
62 #include <Geom2d_Parabola.hxx>
63 #include <Geom2d_Hyperbola.hxx>
64 #include <Geom2d_BezierCurve.hxx>
65 #include <Geom2d_BSplineCurve.hxx>
66
67 #include <GeomLProp.hxx>
68 #include <GeomLProp_CLProps.hxx>
69 #include <Geom2dLProp_CLProps2d.hxx>
70 #include <Geom2dLProp_CurAndInf2d.hxx>
71
72 #include <TColgp_Array1OfPnt.hxx>
73 #include <TColgp_Array1OfPnt2d.hxx>
74 #include <TColStd_Array1OfReal.hxx>
75 #include <TColStd_Array1OfInteger.hxx>
76
77 #include <GeomAbs_SurfaceType.hxx>
78 #include <GeomAbs_CurveType.hxx>
79
80 #include <Precision.hxx>
81
82 #include <stdio.h>
83
84 #include <TColStd_HArray1OfReal.hxx>
85 #include <TColStd_HArray2OfReal.hxx>
86 #include <TColStd_HArray1OfInteger.hxx>
87 #include <TColStd_Array1OfReal.hxx>
88 #include <TColStd_Array1OfInteger.hxx>
89
90 #include <TColGeom_HArray1OfBSplineCurve.hxx>
91 #include <TColGeom2d_HArray1OfBSplineCurve.hxx>
92 #include <Convert_CompPolynomialToPoles.hxx>
93 #include <CPnts_AbscissaPoint.hxx>
94 #include <GCPnts_AbscissaPoint.hxx>
95
96 #include <PLib.hxx> 
97 #include <GeomAbs_Shape.hxx>
98 #include <Geom_Curve.hxx>
99 #include <GeomConvert.hxx>
100 #include <GeomConvert_ApproxCurve.hxx>
101 #include <Geom2dConvert_ApproxCurve.hxx>
102 #include <Geom2d_Curve.hxx>
103
104 #include <GeomAdaptor_HCurve.hxx>
105 #include <GeomAdaptor_Curve.hxx>
106 #include <Geom2dAdaptor_HCurve.hxx>
107 #include <GeomAdaptor_HCurve.hxx>
108 #include <Approx_CurvilinearParameter.hxx>
109 #include <Approx_CurveOnSurface.hxx>
110 #include <Geom_BSplineSurface.hxx>
111
112 #include <AppCont_Function.hxx>
113 #include <Adaptor3d_HCurve.hxx>
114 #include <GeomAdaptor_HCurve.hxx>
115 #include <Approx_FitAndDivide.hxx>
116 #include <Convert_CompBezierCurvesToBSplineCurve.hxx>
117
118 #ifdef _WIN32
119 Standard_IMPORT Draw_Viewer dout;
120 #endif
121
122 //Class is used in fitcurve
123 class CurveEvaluator : public AppCont_Function
124
125 {
126
127 public:
128   Handle(Adaptor3d_HCurve) myCurve;
129
130   CurveEvaluator(const Handle(Adaptor3d_HCurve)& C)
131     : myCurve(C)
132   {
133     myNbPnt = 1;
134     myNbPnt2d = 0;
135   }
136
137   Standard_Real FirstParameter() const
138   {
139     return myCurve->FirstParameter();
140   }
141
142   Standard_Real LastParameter() const
143   {
144     return myCurve->LastParameter();
145   }
146
147   Standard_Boolean Value(const Standard_Real   theT,
148     NCollection_Array1<gp_Pnt2d>& /*thePnt2d*/,
149     NCollection_Array1<gp_Pnt>&   thePnt) const
150   {
151     thePnt(1) = myCurve->Value(theT);
152     return Standard_True;
153   }
154
155   Standard_Boolean D1(const Standard_Real   theT,
156     NCollection_Array1<gp_Vec2d>& /*theVec2d*/,
157     NCollection_Array1<gp_Vec>&   theVec) const
158   {
159     gp_Pnt aDummyPnt;
160     myCurve->D1(theT, aDummyPnt, theVec(1));
161     return Standard_True;
162   }
163 };
164
165
166 //=======================================================================
167 //function : anacurve
168 //purpose  : 
169 //=======================================================================
170
171 static Standard_Integer anacurve (Draw_Interpretor& , Standard_Integer n, const char** a)
172 {
173   if (n < 5) return 1;
174
175   Handle(Geom_Geometry) result;
176   Handle(Geom2d_Curve)  result2d;
177
178   if (!strcmp(a[0],"line")) {
179     if (n == 6)
180       result2d = new Geom2d_Line(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
181                                  gp_Dir2d(Draw::Atof(a[4]),Draw::Atof(a[5])));
182     else if (n == 8)
183       result = new Geom_Line(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
184                              gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7])));
185     else
186       return 1;
187   }
188
189   else if (!strcmp(a[0],"circle")) {
190     if (n == 5)
191       result2d = 
192         new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
193                                    gp_Dir2d(1,0)),
194                           Draw::Atof(a[4]));
195     else if (n == 6)
196       result = 
197         new Geom_Circle(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
198                                gp_Dir(0,0,1)),
199                         Draw::Atof(a[5]));
200     else if (n == 7)
201       result2d =
202         new Geom2d_Circle(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
203                                    gp_Dir2d(Draw::Atof(a[4]),Draw::Atof(a[5]))),
204                           Draw::Atof(a[6]));
205     else if (n == 9)
206       result = 
207         new Geom_Circle(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
208                                gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]))),
209                         Draw::Atof(a[8]));
210     else if (n == 12)
211       result = 
212         new Geom_Circle(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
213                                gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7])),
214                                gp_Dir(Draw::Atof(a[8]),Draw::Atof(a[9]),Draw::Atof(a[10]))),
215                         Draw::Atof(a[11]));
216     else
217       return 1;
218   }
219   
220   else if (!strcmp(a[0],"parabola")) {
221     if (n == 5)
222       result2d = 
223         new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
224                                      gp_Dir2d(1,0)),
225                             Draw::Atof(a[4]));
226     else if (n == 6)
227       result = 
228         new Geom_Parabola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
229                                  gp_Dir(0,0,1)),
230                           Draw::Atof(a[5]));
231     else if (n == 7)
232       result2d = 
233         new Geom2d_Parabola(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
234                                      gp_Dir2d(Draw::Atof(a[4]),Draw::Atof(a[5]))),
235                             Draw::Atof(a[6]));
236     else if (n == 9)
237       result = 
238         new Geom_Parabola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
239                                  gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]))),
240                           Draw::Atof(a[8]));
241     else if (n == 12)
242       result = 
243         new Geom_Parabola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
244                                  gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7])),
245                                  gp_Dir(Draw::Atof(a[8]),Draw::Atof(a[9]),Draw::Atof(a[10]))),
246                           Draw::Atof(a[11]));
247     else
248       return 1;
249   }
250   
251   else if (!strcmp(a[0],"ellipse")) {
252     if (n == 6)
253       result2d = 
254         new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
255                                     gp_Dir2d(1,0)),
256                            Draw::Atof(a[4]),Draw::Atof(a[5]));
257     else if (n == 7)
258       result = 
259         new Geom_Ellipse(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
260                                 gp_Dir(0,0,1)),
261                          Draw::Atof(a[5]),Draw::Atof(a[6]));
262     else if (n == 8)
263       result2d = 
264         new Geom2d_Ellipse(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
265                                     gp_Dir2d(Draw::Atof(a[4]),Draw::Atof(a[5]))),
266                            Draw::Atof(a[6]), Draw::Atof(a[7]));
267     else if (n == 10)
268       result = 
269         new Geom_Ellipse(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
270                                 gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]))),
271                          Draw::Atof(a[8]), Draw::Atof(a[9]));
272     else if (n == 13)
273       result = 
274         new Geom_Ellipse(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
275                                 gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7])),
276                                 gp_Dir(Draw::Atof(a[8]),Draw::Atof(a[9]),Draw::Atof(a[10]))),
277                          Draw::Atof(a[11]), Draw::Atof(a[12]));
278     else
279       return 1;
280   }
281   
282   else if (!strcmp(a[0],"hyperbola")) {
283     if (n == 6)
284       result2d = 
285         new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
286                                       gp_Dir2d(1,0)),
287                              Draw::Atof(a[4]),Draw::Atof(a[5]));
288     else if (n == 7)
289       result = 
290         new Geom_Hyperbola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
291                                   gp_Dir(0,0,1)),
292                            Draw::Atof(a[5]),Draw::Atof(a[6]));
293     else if (n == 8)
294       result2d = 
295         new Geom2d_Hyperbola(gp_Ax22d(gp_Pnt2d(Draw::Atof(a[2]),Draw::Atof(a[3])),
296                                       gp_Dir2d(Draw::Atof(a[4]),Draw::Atof(a[5]))),
297                              Draw::Atof(a[6]), Draw::Atof(a[7]));
298     else if (n == 10)
299       result = 
300         new Geom_Hyperbola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
301                                   gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7]))),
302                            Draw::Atof(a[8]), Draw::Atof(a[9]));
303     else if (n == 13)
304       result = 
305         new Geom_Hyperbola(gp_Ax2(gp_Pnt(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4])),
306                                   gp_Dir(Draw::Atof(a[5]),Draw::Atof(a[6]),Draw::Atof(a[7])),
307                                   gp_Dir(Draw::Atof(a[8]),Draw::Atof(a[9]),Draw::Atof(a[10]))),
308                            Draw::Atof(a[11]), Draw::Atof(a[12]));
309     else
310       return 1;
311   }
312   
313   if (!result.IsNull())
314     DrawTrSurf::Set(a[1],result);
315   else if (!result2d.IsNull())
316     DrawTrSurf::Set(a[1],result2d);
317   else
318     return 1;
319
320   return 0;
321 }
322
323 //=======================================================================
324 //function : polecurve
325 //purpose  : 
326 //=======================================================================
327
328 static Standard_Integer polecurve (Draw_Interpretor& , Standard_Integer n, const char** a)
329 {
330   Standard_Integer k,i;
331
332
333   if (n < 3) return 1;
334
335   if (!strcmp(a[0],"beziercurve")) {
336     
337     Standard_Integer np = Draw::Atoi(a[2]);
338     if (np == 0) return 1;
339     
340     i = (n - 3) / (np);
341     if (i < 3 || i > 4) return 1;
342     Standard_Boolean hasw = i == 4;
343     
344     TColgp_Array1OfPnt poles(1,np);
345     TColStd_Array1OfReal weights(1,np);
346     
347     k = 3;
348     for (i = 1; i <= np; i++) {
349       poles(i).SetCoord(Draw::Atof(a[k]),Draw::Atof(a[k+1]),Draw::Atof(a[k+2]));
350       k += 3;
351       if (hasw) {
352         weights(i) = Draw::Atof(a[k]);
353         k++;
354       }
355     }
356     
357     Handle(Geom_BezierCurve) result;
358     if (hasw)
359       result = new Geom_BezierCurve(poles,weights);
360     else
361       result = new Geom_BezierCurve(poles);
362     
363     DrawTrSurf::Set(a[1],result);
364   }
365   
366   else if (!strcmp((*a[0] == 'p') ? a[0]+1 : a[0],"bsplinecurve")) {
367     Standard_Integer deg = Draw::Atoi(a[2]);
368     Standard_Integer nbk = Draw::Atoi(a[3]);
369
370     TColStd_Array1OfReal    knots(1, nbk);
371     TColStd_Array1OfInteger mults(1, nbk);
372     k = 4;
373     Standard_Integer Sigma = 0;
374     for (i = 1; i<=nbk; i++) {
375       knots( i) = Draw::Atof(a[k]);
376       k++;
377       mults( i) = Draw::Atoi(a[k]);
378       Sigma += mults(i);
379       k++;
380     }
381
382     Standard_Boolean periodic = *a[0] == 'p';
383     Standard_Integer np;
384     if (periodic)
385       np = Sigma - mults(nbk);
386     else
387       np = Sigma - deg  -1;
388
389     TColgp_Array1OfPnt   poles  (1, np);
390     TColStd_Array1OfReal weights(1, np);
391     
392     for (i = 1; i <= np; i++) {
393       poles(i).SetCoord(Draw::Atof(a[k]),Draw::Atof(a[k+1]),Draw::Atof(a[k+2]));
394       k += 3;
395       weights(i) = Draw::Atof(a[k]);
396       k++;
397     }
398     
399     Handle(Geom_BSplineCurve) result =
400       new Geom_BSplineCurve(poles, weights, knots, mults, deg, periodic);
401     DrawTrSurf::Set(a[1],result);
402   }
403   
404   return 0;
405 }
406
407 //=======================================================================
408 //function : polecurve2d
409 //purpose  : 
410 //=======================================================================
411
412 static Standard_Integer polecurve2d (Draw_Interpretor& , Standard_Integer n, const char** a)
413 {
414   Standard_Integer k,i;
415
416
417   if (n < 3) return 1;
418
419   if (!strcmp(a[0],"2dbeziercurve")) {
420     
421     Standard_Integer np = Draw::Atoi(a[2]);
422     if (np == 0) return 1;
423     
424     i = (n - 2) / (np);
425     if (i < 2 || i > 3) return 1;
426     Standard_Boolean hasw = i == 3;
427     
428     TColgp_Array1OfPnt2d poles(1,np);
429     TColStd_Array1OfReal weights(1,np);
430     
431     k = 3;
432     for (i = 1; i <= np; i++) {
433       poles(i).SetCoord(Draw::Atof(a[k]),Draw::Atof(a[k+1]));
434       k += 2;
435       if (hasw) {
436         weights(i) = Draw::Atof(a[k]);
437         k++;
438       }
439     }
440     
441     Handle(Geom2d_BezierCurve) result;
442     if (hasw)
443       result = new Geom2d_BezierCurve(poles,weights);
444     else
445       result = new Geom2d_BezierCurve(poles);
446     
447     DrawTrSurf::Set(a[1],result);
448   }
449   
450   else if (!strcmp((*(a[0]+2) == 'p') ? a[0]+3 : a[0]+2,"bsplinecurve")) {
451     Standard_Integer deg = Draw::Atoi(a[2]);
452     Standard_Integer nbk = Draw::Atoi(a[3]);
453
454     TColStd_Array1OfReal    knots(1, nbk);
455     TColStd_Array1OfInteger mults(1, nbk);
456     k = 4;
457     Standard_Integer Sigma = 0;
458     for (i = 1; i<=nbk; i++) {
459       knots( i) = Draw::Atof(a[k]);
460       k++;
461       mults( i) = Draw::Atoi(a[k]);
462       Sigma += mults(i);
463       k++;
464     }
465
466     Standard_Boolean periodic = *(a[0]+2) == 'p';
467     Standard_Integer np;
468     if (periodic)
469       np = Sigma - mults(nbk);
470     else
471       np = Sigma - deg  -1;
472
473     TColgp_Array1OfPnt2d poles  (1, np);
474     TColStd_Array1OfReal weights(1, np);
475     
476     for (i = 1; i <= np; i++) {
477       poles(i).SetCoord(Draw::Atof(a[k]),Draw::Atof(a[k+1]));
478       k += 2;
479       weights(i) = Draw::Atof(a[k]);
480       k++;
481     }
482     
483     Handle(Geom2d_BSplineCurve) result =
484       new Geom2d_BSplineCurve(poles, weights, knots, mults, deg, periodic);
485     DrawTrSurf::Set(a[1],result);
486   }
487   
488   return 0;
489 }
490
491 //=======================================================================
492 //function : reverse
493 //purpose  : 
494 //=======================================================================
495
496 static Standard_Integer reverse (Draw_Interpretor& , Standard_Integer n, const char** a)
497 {
498   if (n < 2) return 1;
499
500   Standard_Integer i;
501   for (i = 1; i < n; i++) {
502
503     Handle(Geom_Curve) GC = DrawTrSurf::GetCurve(a[i]);
504     if (!GC.IsNull()) {
505       GC->Reverse();
506       Draw::Repaint();
507     }
508     Handle(Geom2d_Curve) GC2d = DrawTrSurf::GetCurve2d(a[i]);
509     if (!GC2d.IsNull()) {
510       GC2d->Reverse();
511       Draw::Repaint();
512     }
513   }
514   return 0;
515 }
516
517 //=======================================================================
518 //function : cmovepole
519 //purpose  : 
520 //=======================================================================
521
522 static Standard_Integer cmovepole (Draw_Interpretor& , Standard_Integer n, const char** a)
523 {
524   if (n < 5) return 1;
525
526   Standard_Real dx = Draw::Atof(a[3]);
527   Standard_Real dy = Draw::Atof(a[4]);
528   Standard_Real dz=0;
529   if (n >= 6) dz = Draw::Atof(a[5]);
530   Standard_Integer Index = Draw::Atoi(a[2]);
531
532   Handle(Geom_BezierCurve) G1 = DrawTrSurf::GetBezierCurve(a[1]);
533   if (!G1.IsNull()) {
534     gp_Pnt P = G1->Pole(Index);
535     P.SetCoord(P.X()+dx, P.Y()+dy, P.Z()+dz);
536     G1->SetPole(Index,P);
537     Draw::Repaint();
538     return 0;
539   }
540
541
542   Handle(Geom_BSplineCurve) G2 = DrawTrSurf::GetBSplineCurve(a[1]);
543   if (!G2.IsNull()) {
544     gp_Pnt P = G2->Pole(Index);
545     P.SetCoord(P.X()+dx, P.Y()+dy, P.Z()+dz);
546     G2->SetPole(Index,P);
547     Draw::Repaint();
548     return 0;
549   }
550
551   Handle(Geom2d_BezierCurve) G3 = DrawTrSurf::GetBezierCurve2d(a[1]);
552   if (!G3.IsNull()) {
553     gp_Pnt2d P = G3->Pole(Index);
554     P.SetCoord(P.X()+dx, P.Y()+dy);
555     G3->SetPole(Index,P);
556     Draw::Repaint();
557     return 0;
558   }
559
560
561   Handle(Geom2d_BSplineCurve) G4 = DrawTrSurf::GetBSplineCurve2d(a[1]);
562   if (!G4.IsNull()) {
563     gp_Pnt2d P = G4->Pole(Index);
564     P.SetCoord(P.X()+dx, P.Y()+dy);
565     G4->SetPole(Index,P);
566     Draw::Repaint();
567     return 0;
568   }
569
570
571
572   return 0;
573 }
574
575 //=======================================================================
576 //function : cmovetangent
577 //purpose  : 
578 //=======================================================================
579
580 static Standard_Integer cmovetangent (Draw_Interpretor& di, Standard_Integer n, const char** a)
581 {
582   Standard_Integer dimension,
583   condition,
584   error_status ;
585   Standard_Real u,
586   x,
587   y,
588   z,
589   tolerance,
590   tx,
591   ty,
592   tz ;
593   u = Draw::Atof(a[2]);
594   x = Draw::Atof(a[3]);
595   y = Draw::Atof(a[4]);
596   z = 0.0e0,
597   tolerance = 1.0e-5 ;
598   dimension = 3 ;
599   if (n <= 8) {
600     dimension = 2 ;
601     if (n < 7) {
602       return 1 ;
603     }
604   }
605   else {
606     dimension = 3 ;
607     if (n < 9) {
608       return 1 ;
609     }
610   }
611   condition = 0 ;
612   error_status  = 0 ;
613   if (dimension == 3) {
614     Handle(Geom_BSplineCurve) G2 = DrawTrSurf::GetBSplineCurve(a[1]);
615     if (!G2.IsNull()) {
616       z  = Draw::Atof(a[5]) ;
617       tx = Draw::Atof(a[6]) ;
618       ty = Draw::Atof(a[7]) ;
619       tz = Draw::Atof(a[8]) ;
620       if (n == 10) {
621         condition = Max(Draw::Atoi(a[9]), -1)  ;
622         condition = Min(condition, G2->Degree()-1) ;
623       }
624       gp_Pnt p;
625       gp_Vec tangent ;
626       p.SetCoord(x,y,z);
627       tangent.SetCoord(tx,ty,tz) ;
628       
629       G2->MovePointAndTangent(u, 
630                               p, 
631                               tangent,
632                               tolerance,
633                               condition,
634                               condition,
635                               error_status) ;
636       if (! error_status) {
637         Draw::Repaint();
638         }
639       else {
640         di << "Not enought degree of freedom increase degree please\n";
641       }
642       
643       return 0;
644     }
645   }
646   else {
647     Handle(Geom2d_BSplineCurve) G2 = DrawTrSurf::GetBSplineCurve2d(a[1]);
648     if (!G2.IsNull()) {
649       tx = Draw::Atof(a[5]) ;
650       ty = Draw::Atof(a[6]) ;
651       if (n == 8) {
652         condition = Max(Draw::Atoi(a[7]), -1)  ;
653         condition = Min(condition, G2->Degree()-1) ;
654       }
655       gp_Pnt2d p;
656       gp_Vec2d tangent ;
657       p.SetCoord(x,y);
658       tangent.SetCoord(tx,ty) ;
659       
660       G2->MovePointAndTangent(u, 
661                               p, 
662                               tangent,
663                               tolerance,
664                               condition,
665                               condition,
666                               error_status) ;
667       if (! error_status) {
668         Draw::Repaint();
669         }
670       else {
671         di << "Not enought degree of freedom increase degree please\n";
672       }
673       
674       return 0;
675     }
676    } 
677   return 0;
678 }
679
680
681 //=======================================================================
682 //function : cmovepoint
683 //purpose  : 
684 //=======================================================================
685
686 static Standard_Integer cmovepoint (Draw_Interpretor& , Standard_Integer n, const char** a)
687 {
688   if (n < 5) return 1;
689
690   Standard_Real dx = Draw::Atof(a[3]);
691   Standard_Real dy = Draw::Atof(a[4]);
692   Standard_Real dz=0;
693   if (n >= 6 && n != 7) dz = Draw::Atof(a[5]);
694   Standard_Real u = Draw::Atof(a[2]);
695   Standard_Integer index1 = 0;
696   Standard_Integer index2 = 0;
697   Standard_Integer fmodif, lmodif;
698   if (n == 7) {
699     index1 = Draw::Atoi(a[5]);
700     index2 = Draw::Atoi(a[6]);
701   }
702   else if (n == 8) {
703     index1 = Draw::Atoi(a[6]);
704     index2 = Draw::Atoi(a[7]);
705   }
706
707   Handle(Geom_BSplineCurve) G2 = DrawTrSurf::GetBSplineCurve(a[1]);
708   if (!G2.IsNull()) {
709     if (index1 == 0) {
710       index1 = 2;
711       index2 = G2->NbPoles()-1;
712     }
713     gp_Pnt p;
714     G2->D0(u, p);
715     p.SetCoord(p.X()+dx, p.Y()+dy, p.Z()+dz);
716     G2->MovePoint(u, p, index1, index2, fmodif, lmodif);
717     Draw::Repaint();
718     return 0;
719   }
720
721   Handle(Geom2d_BSplineCurve) G4 = DrawTrSurf::GetBSplineCurve2d(a[1]);
722   if (!G4.IsNull()) {
723     if (index1 == 0) {
724       index1 = 2;
725       index2 = G4->NbPoles()-1;
726     }
727     gp_Pnt2d p;
728     G4->D0(u, p);
729     p.SetCoord(p.X()+dx, p.Y()+dy);
730     G4->MovePoint(u, p, index1, index2, fmodif, lmodif);
731     Draw::Repaint();
732     return 0;
733   }
734   return 0;
735 }
736
737 //=======================================================================
738 //function : cinsertknot
739 //purpose  : 
740 //=======================================================================
741
742 static Standard_Integer cinsertknot (Draw_Interpretor& , Standard_Integer n, const char** a)
743 {
744   if (n < 4) return 1;
745
746   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
747   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
748
749   if (GBs.IsNull() && GBs2d.IsNull()) return 1;
750
751   if (n <= 4) {
752     Standard_Real    knot = Draw::Atof(a[2]);
753     Standard_Integer mult = 1;
754     if (n == 4) mult = Draw::Atoi(a[3]);
755     if (!GBs.IsNull())
756       GBs->InsertKnot(knot,mult,Precision::PConfusion());
757     else
758       GBs2d->InsertKnot(knot,mult,Precision::PConfusion());
759   }
760
761   else {
762     // multiple insertion
763     if (n % 2 != 0) return 1;
764     Standard_Integer i,nbk = (n-2) / 2;
765     TColStd_Array1OfReal    knots(1,nbk);
766     TColStd_Array1OfInteger mults(1,nbk);
767     for (i = 2; i < n; i += 2) {
768       knots(i/2) = Draw::Atof(a[i]);
769       mults(i/2) = Draw::Atoi(a[i+1]);
770     }
771
772     if (!GBs.IsNull())
773       GBs->InsertKnots(knots,mults,Precision::PConfusion());
774     else
775       GBs2d->InsertKnots(knots,mults,Precision::PConfusion());
776
777   }
778
779   Draw::Repaint();
780   return 0;
781 }
782
783 //=======================================================================
784 //function : csetknot
785 //purpose  : 
786 //=======================================================================
787
788 static Standard_Integer csetknot (Draw_Interpretor& , Standard_Integer n, const char** a)
789 {
790   if (n < 4) return 1;
791
792   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
793   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
794
795   if (GBs.IsNull() && GBs2d.IsNull()) return 1;
796
797   Standard_Integer index = Draw::Atoi(a[2]);
798   Standard_Real    knot  = Draw::Atof(a[3]);
799
800   if ( n == 4) {
801     if (!GBs.IsNull())
802       GBs->SetKnot(index,knot);
803     else
804       GBs2d->SetKnot(index,knot);
805   }
806   else {
807     Standard_Integer mult  = Draw::Atoi(a[4]);
808     if (!GBs.IsNull())
809       GBs->SetKnot(index,knot,mult);
810     else
811       GBs2d->SetKnot(index,knot,mult);
812   }
813
814   Draw::Repaint();
815   return 0;
816 }
817
818 //=======================================================================
819 //function : cremknot
820 //purpose  : 
821 //=======================================================================
822
823 static Standard_Integer cremknot (Draw_Interpretor& di, Standard_Integer n, const char** a)
824 {
825   if (n < 3) return 1;
826
827   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
828   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
829
830   if (GBs.IsNull() && GBs2d.IsNull()) return 1;
831
832   Standard_Integer index = Draw::Atoi(a[2]);
833   Standard_Integer mult  = 0;
834   if (n >= 4) mult = Draw::Atoi(a[3]);
835
836   Standard_Real tol = RealLast();
837   if (n >= 5) tol = Draw::Atof(a[4]);
838
839   if (!GBs.IsNull()) {
840     if (!GBs->RemoveKnot(index,mult,tol))
841       di << "Remove knots failed\n";
842   }
843   else {
844     if (!GBs2d->RemoveKnot(index,mult,tol))
845       di << "Remove knots failed\n";
846   }
847
848   Draw::Repaint();
849   return 0;
850 }
851
852 //=======================================================================
853 //function : increasedegree
854 //purpose  : 
855 //=======================================================================
856
857 static Standard_Integer increasedegree (Draw_Interpretor& , Standard_Integer n, const char** a)
858 {
859   if (n < 3) return 1;
860
861   Standard_Integer Deg = Draw::Atoi(a[2]);
862
863   Handle(Geom_BezierCurve) GBz = DrawTrSurf::GetBezierCurve(a[1]);
864   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
865   Handle(Geom2d_BezierCurve) GBz2d = DrawTrSurf::GetBezierCurve2d(a[1]);
866   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
867
868   if (!GBz.IsNull()) 
869     GBz->Increase(Deg);
870   else if (!GBs.IsNull())
871     GBs->IncreaseDegree(Deg);
872   else if (!GBz2d.IsNull()) 
873     GBz2d->Increase(Deg);
874   else if (!GBs2d.IsNull())
875     GBs2d->IncreaseDegree(Deg);
876   else
877     return 1;
878
879   Draw::Repaint();
880   return 0;
881 }
882
883 //=======================================================================
884 //function : removepole
885 //purpose  : 
886 //=======================================================================
887
888 static Standard_Integer removepole (Draw_Interpretor& di, Standard_Integer n, const char** a)
889 {
890   if (n < 3) return 1;
891
892   Standard_Integer Index = Draw::Atoi(a[2]);
893
894   Handle(Geom_BezierCurve)   GBZ   = DrawTrSurf::GetBezierCurve(a[1]);
895   Handle(Geom2d_BezierCurve) GBZ2d = DrawTrSurf::GetBezierCurve2d(a[1]);
896   if (!GBZ.IsNull()) {
897     GBZ->RemovePole(Index);
898   }
899   else if (!GBZ2d.IsNull()) {
900     GBZ2d->RemovePole(Index);
901   }
902   else {
903     di << "rempole needs a bezier curve";
904     return 1;
905   }
906
907   Draw::Repaint();
908   return 0;
909 }
910
911 //=======================================================================
912 //function : insertpole
913 //purpose  : 
914 //=======================================================================
915
916 static Standard_Integer insertpole (Draw_Interpretor& di, Standard_Integer n, const char** a)
917 {
918   if (n < 6) return 1;
919
920   Standard_Integer Index = Draw::Atoi(a[2]);
921
922   Handle(Geom_BezierCurve)   GBZ   = DrawTrSurf::GetBezierCurve(a[1]);
923   Handle(Geom2d_BezierCurve) GBZ2d = DrawTrSurf::GetBezierCurve2d(a[1]);
924   if (!GBZ.IsNull()) {
925     gp_Pnt P (Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]));
926     if ( n == 7)
927       GBZ->InsertPoleAfter(Index,P,Draw::Atof(a[6]));
928     else
929       GBZ->InsertPoleAfter(Index,P);
930   }
931   else if (!GBZ2d.IsNull()) {
932     gp_Pnt2d P (Draw::Atof(a[3]),Draw::Atof(a[4]));
933     if ( n == 6)
934       GBZ2d->InsertPoleAfter(Index,P,Draw::Atof(a[5]));
935     else
936       GBZ2d->InsertPoleAfter(Index,P);
937   }
938   else {
939     di << "insertpole needs a bezier curve";
940     return 1;
941   }
942
943   Draw::Repaint();
944   return 0;
945 }
946
947 //=======================================================================
948 //function : cfindp
949 //purpose  : 
950 //=======================================================================
951
952 static Standard_Integer cfindp (Draw_Interpretor& , Standard_Integer n, const char** a)
953 {
954   if (n < 6) return 1;
955
956   Standard_Integer Index = 0;
957   Standard_Integer view = Draw::Atoi(a[2]);
958   Standard_Real x = Draw::Atof(a[3]);
959   Standard_Real y = Draw::Atof(a[4]);
960
961   Draw_Display d = dout.MakeDisplay(view);
962
963   Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
964
965   Handle(DrawTrSurf_BezierCurve) DBz = 
966     Handle(DrawTrSurf_BezierCurve)::DownCast(D);
967   if( !DBz.IsNull())
968     DBz->FindPole( x, y, d, 5, Index);
969   else {
970     Handle(DrawTrSurf_BSplineCurve) DBs = 
971       Handle(DrawTrSurf_BSplineCurve)::DownCast(D);
972     if (!DBs.IsNull())
973       DBs->FindPole( x, y, d, 5, Index);
974     else {
975       Handle(DrawTrSurf_BezierCurve2d) DBz2d = 
976         Handle(DrawTrSurf_BezierCurve2d)::DownCast(D);
977       if( !DBz2d.IsNull())
978         DBz2d->FindPole( x, y, d, 5, Index);
979       else {
980         Handle(DrawTrSurf_BSplineCurve2d) DBs2d = 
981           Handle(DrawTrSurf_BSplineCurve2d)::DownCast(D);
982         if (!DBs2d.IsNull())
983           DBs2d->FindPole( x, y, d, 5, Index);
984         else 
985           return 1;
986       }
987     }
988   }
989   
990   Draw::Set(a[5],Index);
991   
992   return 0;
993 }
994
995
996 //=======================================================================
997 //function : csetperiodic
998 //purpose  : 
999 //=======================================================================
1000
1001 static Standard_Integer csetperiodic (Draw_Interpretor& , Standard_Integer n, const char** a)
1002 {
1003   if (n < 2) return 1;
1004
1005   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
1006   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
1007   
1008   if (GBs.IsNull() && GBs2d.IsNull()) return 1;
1009   
1010   if (!strcmp(a[0],"setperiodic")) {
1011     if (!GBs.IsNull()) 
1012       GBs->SetPeriodic();
1013     else
1014       GBs2d->SetPeriodic();
1015   }
1016   else if (!strcmp(a[0],"setnotperiodic")) {
1017     if (!GBs.IsNull()) 
1018       GBs->SetNotPeriodic();
1019     else
1020       GBs2d->SetNotPeriodic();
1021   }
1022
1023   Draw::Repaint();
1024   return 0;
1025 }
1026
1027 //=======================================================================
1028 //function : value
1029 //purpose  : 
1030 //=======================================================================
1031
1032 static Standard_Integer value (Draw_Interpretor& ,
1033                                Standard_Integer n, const char** a)
1034 {
1035   if (n < 4) return 1;
1036
1037   Handle(Geom_Curve) GC = DrawTrSurf::GetCurve(a[1]);
1038   if (GC.IsNull()) return 1;
1039
1040   Standard_Real U = Draw::Atof(a[2]);
1041
1042   Standard_Boolean DrawPoint = ( n%3 == 1);
1043   if ( DrawPoint) n--;
1044
1045   gp_Pnt P;
1046   if (n > 6) {
1047     if (n < 9) return 1;
1048     gp_Vec D1;
1049     if (n > 9) {
1050       if (n < 12) return 1;
1051       gp_Vec D2;
1052       GC->D2(U,P,D1,D2);
1053       Draw::Set(a[9] ,D2.X());
1054       Draw::Set(a[10],D2.Y());
1055       Draw::Set(a[11],D2.Z());
1056     }
1057     else 
1058       GC->D1(U,P,D1);
1059     Draw::Set(a[6],D1.X());
1060     Draw::Set(a[7],D1.Y());
1061     Draw::Set(a[8],D1.Z());
1062   }
1063   else 
1064     GC->D0(U,P);
1065
1066   if ( n > 3) {
1067     Draw::Set(a[3],P.X());
1068     Draw::Set(a[4],P.Y());
1069     Draw::Set(a[5],P.Z());
1070   }
1071   if ( DrawPoint) {
1072     DrawTrSurf::Set(a[n],P);
1073   }
1074   
1075   return 0;
1076 }
1077
1078
1079 //=======================================================================
1080 //function : value2d
1081 //purpose  : 
1082 //=======================================================================
1083
1084 static Standard_Integer value2d (Draw_Interpretor& , 
1085                                  Standard_Integer n, const char** a)
1086 {
1087   if (n < 4) return 1;
1088
1089   Handle(Geom2d_Curve) GC = DrawTrSurf::GetCurve2d(a[1]);
1090   if (GC.IsNull()) return 1;
1091
1092   Standard_Real U = Draw::Atof(a[2]);
1093
1094   Standard_Boolean DrawPoint = ( n%2 == 0);
1095   if ( DrawPoint ) n--;
1096
1097   gp_Pnt2d P;
1098   if (n > 5) {
1099     if (n < 7) return 1;
1100     gp_Vec2d D1;
1101     if (n > 7) {
1102       if (n < 9) return 1;
1103       gp_Vec2d D2;
1104       GC->D2(U,P,D1,D2);
1105       Draw::Set(a[7] ,D2.X());
1106       Draw::Set(a[8],D2.Y());
1107     }
1108     else 
1109       GC->D1(U,P,D1);
1110     Draw::Set(a[5],D1.X());
1111     Draw::Set(a[6],D1.Y());
1112   }
1113   else 
1114     GC->D0(U,P);
1115
1116   if ( n > 3 ) {
1117     Draw::Set(a[3],P.X());
1118     Draw::Set(a[4],P.Y());
1119   }
1120   if ( DrawPoint ) {
1121     DrawTrSurf::Set(a[n], P);
1122   }
1123   
1124   return 0;
1125 }
1126
1127 //=======================================================================
1128 //function : segment
1129 //purpose  : 
1130 //=======================================================================
1131
1132 static Standard_Integer segment (Draw_Interpretor& , Standard_Integer n, const char** a)
1133 {
1134   if (n < 4 || n > 5) return 1;
1135
1136   Handle(Geom_BezierCurve) GBz = DrawTrSurf::GetBezierCurve(a[1]);
1137   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
1138   Handle(Geom2d_BezierCurve) GBz2d = DrawTrSurf::GetBezierCurve2d(a[1]);
1139   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
1140
1141   Standard_Real f = Draw::Atof(a[2]), l = Draw::Atof(a[3]);
1142
1143   Standard_Real aTolerance = Precision::PConfusion();
1144   if (n == 5)
1145     aTolerance = Draw::Atof(a[4]);
1146
1147   if (!GBz.IsNull()) 
1148     GBz->Segment(f,l);
1149   else if (!GBs.IsNull())
1150     GBs->Segment(f, l, aTolerance);
1151   else if (!GBz2d.IsNull()) 
1152     GBz2d->Segment(f,l);
1153   else if (!GBs2d.IsNull())
1154     GBs2d->Segment(f, l, aTolerance);
1155   else
1156     return 1;
1157
1158   Draw::Repaint();
1159   return 0;
1160 }
1161
1162
1163 //=======================================================================
1164 //function : setorigin
1165 //purpose  : 
1166 //=======================================================================
1167
1168 static Standard_Integer setorigin (Draw_Interpretor& , Standard_Integer n, const char** a)
1169 {
1170   if (n < 3) return 1;
1171
1172   Handle(Geom_BSplineCurve) GBs = DrawTrSurf::GetBSplineCurve(a[1]);
1173   Handle(Geom2d_BSplineCurve) GBs2d = DrawTrSurf::GetBSplineCurve2d(a[1]);
1174
1175   if (!GBs.IsNull())
1176     GBs->SetOrigin(Draw::Atoi(a[2])); 
1177   if (!GBs2d.IsNull())
1178     GBs2d->SetOrigin(Draw::Atoi(a[2])); 
1179   else
1180     return 1;
1181
1182   Draw::Repaint();
1183   return 0;
1184 }
1185
1186
1187 //=======================================================================
1188 //function : point
1189 //purpose  : 
1190 //=======================================================================
1191
1192 static Standard_Integer point(Draw_Interpretor& , Standard_Integer n, const char** a)
1193 {
1194   if (n < 4) return 1;
1195   if (n >= 5) {
1196     gp_Pnt P(Draw::Atof(a[2]),Draw::Atof(a[3]),Draw::Atof(a[4]));
1197     DrawTrSurf::Set(a[1],P);
1198   }
1199   else {
1200     gp_Pnt2d P(Draw::Atof(a[2]),Draw::Atof(a[3]));
1201     DrawTrSurf::Set(a[1],P);
1202   }
1203
1204   return 0;
1205 }
1206
1207 //=======================================================================
1208 //function : coord
1209 //purpose  : 
1210 //=======================================================================
1211
1212 static Standard_Integer coord(Draw_Interpretor&,
1213                               Standard_Integer n, const char** a) 
1214 {
1215   if ( n == 4) {
1216     gp_Pnt2d P;
1217     if ( !DrawTrSurf::GetPoint2d(a[1],P)) return 1;
1218     Draw::Set(a[2],P.X());
1219     Draw::Set(a[3],P.Y());
1220   }
1221   else if ( n == 5) {
1222     gp_Pnt  P;
1223     if ( !DrawTrSurf::GetPoint(a[1],P)) return 1;
1224     Draw::Set(a[2],P.X());
1225     Draw::Set(a[3],P.Y());
1226     Draw::Set(a[4],P.Z());
1227   }
1228   else 
1229     return 1;
1230
1231   return 0;
1232 }
1233
1234 //=======================================================================
1235 //function : 
1236 //purpose  : 
1237 //=======================================================================
1238 static Standard_Integer minmaxcurandinf(Draw_Interpretor& di, 
1239                                    Standard_Integer argc, const char** argv)
1240 {
1241   if (argc < 2) return 1;
1242
1243   Handle(Geom2d_Curve)  C1 = DrawTrSurf::GetCurve2d(argv[1]);
1244   if (C1.IsNull()) return 1;
1245
1246   Draw_Color              Couleur;
1247   Geom2dLProp_CurAndInf2d Sommets;  
1248
1249   Sommets.PerformCurExt (C1);
1250   if (Sommets.IsDone() && !Sommets.IsEmpty()) {
1251     for (Standard_Integer i = 1; i <= Sommets.NbPoints(); i++){      
1252       Couleur = Draw_vert;
1253       if (Sommets.Type(i) == LProp_MinCur) {
1254         Couleur = Draw_orange;
1255         di << "  Maximum of curvature at U ="<<Sommets.Parameter(i)<<"\n";
1256       }
1257       else {
1258         di << "  Minimum of curvature at U ="<<Sommets.Parameter(i)<<"\n";
1259       }
1260       gp_Pnt2d P = C1->Value(Sommets.Parameter(i));
1261       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Couleur); 
1262       dout << dr;
1263     }
1264     dout.Flush();
1265   }
1266    
1267   Geom2dLProp_CurAndInf2d Sommets2;
1268   Sommets2.PerformInf (C1);
1269   
1270   if (Sommets2.IsDone() && !Sommets2.IsEmpty()) {
1271     for (Standard_Integer i = 1; i <= Sommets2.NbPoints(); i++){
1272       gp_Pnt2d P = C1->Value(Sommets2.Parameter(i));
1273       Handle(Draw_Marker2D) dr = new Draw_Marker2D(P,Draw_Plus,Draw_bleu); 
1274       dout << dr;
1275       di << "  Inflexion at U ="<<Sommets2.Parameter(i)<<"\n";
1276     }
1277     dout.Flush();
1278   }
1279   return 0;
1280 }
1281 //=======================================================================
1282 //function :  shcurvature
1283 //purpose  :  affiche le peigne de courbure
1284 //=======================================================================
1285 static Standard_Integer shcurvature(Draw_Interpretor&, 
1286                                    Standard_Integer argc, const char** argv)
1287 {
1288   if (argc < 2) return 1;
1289
1290    Handle(DrawTrSurf_Curve2d) C2d =  Handle(DrawTrSurf_Curve2d)
1291                                   ::DownCast(Draw::Get(argv[1]));
1292    Handle(DrawTrSurf_Curve) C3d =  Handle(DrawTrSurf_Curve)
1293                                   ::DownCast(Draw::Get(argv[1]));
1294    
1295   if (C2d.IsNull()) {
1296     if (C3d.IsNull()) return 1;
1297     C3d->ShowCurvature();
1298   }
1299   else {
1300     C2d->ShowCurvature();
1301   }
1302   Draw::Repaint();
1303   return 0;
1304 }
1305
1306 //=======================================================================
1307 //function :  clcurvature
1308 //purpose  :  efface le peigne de courbure
1309 //=======================================================================
1310 static Standard_Integer clcurvature(Draw_Interpretor&, 
1311                                    Standard_Integer argc, const char** argv)
1312 {
1313   if (argc < 2) return 1; 
1314    Handle(DrawTrSurf_Curve2d) C2d =  Handle(DrawTrSurf_Curve2d)
1315                                   ::DownCast(Draw::Get(argv[1]));
1316    Handle(DrawTrSurf_Curve) C3d =  Handle(DrawTrSurf_Curve)
1317                                   ::DownCast(Draw::Get(argv[1]));
1318
1319   if (C2d.IsNull()) {
1320     if (C3d.IsNull()) return 1;
1321     C3d->ClearCurvature();
1322   }
1323   else {
1324     C2d->ClearCurvature();
1325   }
1326   Draw::Repaint();
1327   return 0;
1328 }
1329
1330 //=======================================================================
1331 //function :  radiusmax
1332 //purpose  :  definit le rayon de courbure maximum a afficher
1333 //=======================================================================
1334 static Standard_Integer radiusmax(Draw_Interpretor&, 
1335                                   Standard_Integer argc, const char** argv)
1336 {
1337   if (argc < 3) return 1; 
1338   Standard_Real Radius = Draw::Atof(argv[2]);
1339    Handle(DrawTrSurf_Curve2d) C2d =  Handle(DrawTrSurf_Curve2d)
1340                                   ::DownCast(Draw::Get(argv[1]));
1341    Handle(DrawTrSurf_Curve) C3d =  Handle(DrawTrSurf_Curve)
1342                                   ::DownCast(Draw::Get(argv[1]));
1343
1344   if (C2d.IsNull()) {
1345     if (C3d.IsNull()) return 1;
1346     C3d->SetRadiusMax(Radius);
1347   }
1348   else {
1349     C2d->SetRadiusMax(Radius);
1350   }
1351   Draw::Repaint();
1352   return 0;
1353 }
1354
1355 //=======================================================================
1356 //function :  radiusratio
1357 //purpose  :  definit le ratio du rayon de courbure a afficher
1358 //=======================================================================
1359 static Standard_Integer radiusratio(Draw_Interpretor&, 
1360                                   Standard_Integer argc, const char** argv)
1361 {
1362   if (argc < 3) return 1;
1363   Standard_Real Ratio = Draw::Atof(argv[2]);
1364   Handle(DrawTrSurf_Curve2d) C2d =  Handle(DrawTrSurf_Curve2d)
1365                                   ::DownCast(Draw::Get(argv[1]));
1366   Handle(DrawTrSurf_Curve) C3d =  Handle(DrawTrSurf_Curve)
1367                                   ::DownCast(Draw::Get(argv[1]));
1368
1369   if (C2d.IsNull()) { 
1370     if (C3d.IsNull()) return 1;
1371     C3d->SetRadiusRatio(Ratio);
1372   }
1373   else {
1374     C2d->SetRadiusRatio(Ratio);
1375   }
1376   Draw::Repaint();
1377   return 0;
1378 }
1379
1380 //=======================================================================
1381 //function : 
1382 //purpose  : 
1383 //=======================================================================
1384 static Standard_Integer localprop(Draw_Interpretor& di, 
1385                                   Standard_Integer argc, const char** argv)
1386 {
1387   if (argc < 3) return 1;
1388
1389   Standard_Real U =  Draw::Atof(argv[2]);
1390
1391   Handle(Geom2d_Curve)  C2d = DrawTrSurf::GetCurve2d(argv[1]);
1392   Handle(Geom_Curve)    C3d;
1393
1394
1395   if (C2d.IsNull()) {
1396     C3d = DrawTrSurf::GetCurve(argv[1]);
1397     if (C3d.IsNull()) return 1;
1398     GeomLProp_CLProps Prop (C3d,2,Precision::Confusion());
1399     Prop.SetParameter(U);
1400     Handle(Draw_Marker3D)drp = new Draw_Marker3D(Prop.Value(),
1401                                                  Draw_Plus,
1402                                                  Draw_vert );
1403     dout << drp;
1404     if (Prop.IsTangentDefined()) {
1405       Standard_Real K = Prop.Curvature();
1406       di <<" Curvature : "<<K<<"\n";
1407
1408       if (Abs(K) > Precision::Confusion()) {
1409         Standard_Real R = 1/Abs(K);
1410         gp_Pnt        Center;
1411         Prop.CentreOfCurvature(Center);
1412         gp_Dir Tang;
1413         gp_Dir Nor;
1414         Prop.Tangent(Tang);
1415         Prop.Normal(Nor);
1416         gp_Dir AxC = Nor^Tang;
1417         gp_Ax2 Axe(Center,AxC,Nor);
1418         Handle(Geom_Circle) Cir3d = new Geom_Circle(Axe,R);
1419         Handle(DrawTrSurf_Curve) dr;
1420         dr = new DrawTrSurf_Curve(Cir3d);
1421         dout << dr;
1422         dout.Flush();
1423       }
1424     }
1425     else 
1426       di <<"Tangent undefined.\n";  
1427   }
1428   else {
1429     Geom2dLProp_CLProps2d Prop (C2d,2,Precision::Confusion());
1430     Prop.SetParameter(U);
1431     Handle(Draw_Marker2D) drp = new Draw_Marker2D(Prop.Value(),
1432                                                   Draw_Plus,
1433                                                   Draw_vert);
1434     dout << drp;
1435     if (Prop.IsTangentDefined()) {
1436       Standard_Real K = Prop.Curvature();
1437       gp_Pnt2d      Center;
1438
1439       di <<" Curvature : "<<K<<"\n";
1440
1441       if (Abs(K) > Precision::Confusion()) {
1442         Standard_Real R = 1/Abs(K);
1443         Prop.CentreOfCurvature(Center);
1444         gp_Ax2d Axe(Center,gp::DX2d());
1445         Handle(Geom2d_Circle) Cir2d = new Geom2d_Circle(Axe,R);
1446         Handle(DrawTrSurf_Curve2d) dr;
1447         dr = new DrawTrSurf_Curve2d(Cir2d,Draw_rouge,30,Standard_False);
1448         dout << dr;
1449         dout.Flush();
1450       }
1451     }
1452     else 
1453       di <<"Tangent undefined.\n";
1454   }
1455   return 0;
1456 }  
1457 //=======================================================================
1458 //function : rawcont
1459 //purpose  : 
1460 //=======================================================================
1461
1462 static Standard_Integer rawcont(Draw_Interpretor& di, Standard_Integer n, const char** a)
1463 {
1464   if (n < 5) return 1;
1465
1466   Handle(Geom_Curve) GC1;
1467   GC1 = DrawTrSurf::GetCurve(a[1]);
1468   Handle(Geom_Curve) GC2;
1469   GC2 = DrawTrSurf::GetCurve(a[2]);
1470   Standard_Real param1 =
1471     Draw::Atof(a[3]) ;
1472   Standard_Real param2 =
1473     Draw::Atof(a[4]) ;
1474   if (GC1.IsNull() || GC2.IsNull())
1475     return 1;
1476   gp_Pnt a_point1,
1477     a_point2 ;
1478   GC1->D0(param1,
1479           a_point1) ;
1480   GC2->D0(param2,
1481           a_point2) ;
1482   if (a_point2.SquareDistance(a_point1) < Precision::Confusion()) {
1483     GeomAbs_Shape cont =
1484       GeomLProp::Continuity(GC1,
1485                             GC2,
1486                             param1,
1487                             param2,
1488                             Standard_True,
1489                             Standard_True,
1490                             Precision::Confusion(),
1491                             Precision::Angular()) ;
1492     switch (cont) {
1493     case GeomAbs_C0: 
1494       di << " C0 Continuity \n" ;
1495       break ;
1496     case GeomAbs_G1:
1497       di << " G1 Continuity \n" ;
1498       break ;
1499     case GeomAbs_C1 :
1500       di << " C1 Continuity \n" ;
1501       break ;
1502     case GeomAbs_G2 :
1503       di << " G2 Continuity \n" ;
1504       break ; 
1505     case GeomAbs_C2 :
1506       di << " C2 Continuity \n" ;
1507       break ; 
1508     case GeomAbs_C3 :
1509       di << " C3 Continuity \n" ;
1510       break ; 
1511     case GeomAbs_CN :
1512       di << " CN Continuity \n" ;
1513       break ; 
1514     default:
1515       break ; 
1516     }
1517   }
1518   else {
1519     di << " not C0 continuity \n" ;
1520   }
1521   return 0 ;
1522 }
1523 //=======================================================================
1524 //function : approxcurveonsurf
1525 //purpose  : 
1526 //=======================================================================
1527 static Standard_Integer approxcurveonsurf(Draw_Interpretor& di, Standard_Integer n, const char** a)
1528 {
1529   Standard_Real Tol = 1.e-7;              // Tolerance (default 0.1mm) 
1530   GeomAbs_Shape Continuity = GeomAbs_C1;  // Continuity order : 0, 1 or 2 (default 1)
1531   Standard_Integer MaxDeg = 14;           // Maximum degree
1532   Standard_Integer MaxSeg = 16; /*1*/          // Maximum number of segments
1533
1534   if ( n>8 || n<4) return 1;
1535
1536   if (n>4) Tol = Max(Draw::Atof(a[4]),1.e-10);
1537
1538   if (n>5) {
1539     if (Draw::Atoi(a[5]) == 0) Continuity = GeomAbs_C0;
1540     if (Draw::Atoi(a[5]) == 2) Continuity = GeomAbs_C2;
1541   }
1542
1543   if (n>6) {
1544     MaxDeg = Draw::Atoi(a[6]);
1545     if (MaxDeg<1 || MaxDeg>14) MaxDeg = 14;
1546   }
1547
1548   if (n>7) MaxSeg = Draw::Atoi(a[7]);
1549   Handle(Geom2d_Curve) curve2d = DrawTrSurf::GetCurve2d(a[2]);
1550   Handle(Geom_Surface) Surf = DrawTrSurf::GetSurface(a[3]);
1551
1552   Handle(Geom2dAdaptor_HCurve) A2d = new (Geom2dAdaptor_HCurve)(curve2d);
1553   Handle(GeomAdaptor_HSurface) AS = new (GeomAdaptor_HSurface)(Surf);
1554
1555   Approx_CurveOnSurface App(A2d, AS, A2d->FirstParameter(), A2d->LastParameter(),
1556                             Tol,  Continuity,  MaxDeg, MaxSeg,
1557                             Standard_True, Standard_False);
1558
1559   if(App.HasResult()) {
1560     Handle(Geom_BSplineCurve) BSCurve = App.Curve3d(); 
1561     DrawTrSurf::Set(a[1], BSCurve);
1562     return 0;
1563   }
1564
1565   di << "Approximation failed !\n";
1566   return 1;
1567                             
1568 }
1569
1570 //=======================================================================
1571 //function : approxcurve
1572 //purpose  : 
1573 //=======================================================================
1574 static Standard_Integer approxcurve(Draw_Interpretor& di, Standard_Integer n, const char** a)
1575
1576   Standard_Real Tol = 1.e-7;              // Tolerance (default 0.1mm) 
1577   GeomAbs_Shape Continuity = GeomAbs_C1;  // Continuity order : 0, 1 or 2 (default 1)
1578   Standard_Integer MaxDeg = 14;           // Maximum degree
1579   Standard_Integer MaxSeg = 16;           // Maximum number of segments
1580   
1581   Standard_Integer Case, shift;
1582 // Case == 1 : 3d approximation without reparametrization
1583 // Case == 2 : 2d approximation without reparametrization
1584 // Case == 3 : 3d approximation with reparametrization
1585 // Case == 4 : curve_on_surface approximation with reparametrization
1586 // Case == 5 : 2 curves_on_surfaces approximation with reparametrization
1587
1588   Handle(Geom_Curve) curve;
1589   Handle(Geom2d_Curve) curve2d, curve2d2;
1590   Handle(Geom_Surface) surface, surface2;
1591
1592   if(n < 2) return 1;
1593
1594   if (!strcmp(a[1],"-L")) {
1595 // aproximation with curvilinear abscissa reparametrization
1596     if (n > 11 || n < 4) return 1;
1597     Tol = 1.e-4;
1598     curve = DrawTrSurf::GetCurve(a[3]);
1599     if (!curve.IsNull()) {
1600       shift = 4;
1601       Case = 3;
1602     }
1603     else {
1604 // approx curve_on_surface
1605       if (n < 5) return 1;
1606       curve2d = DrawTrSurf::GetCurve2d(a[3]); 
1607       surface = DrawTrSurf::GetSurface(a[4]);
1608       if (curve2d.IsNull() || surface.IsNull()) {
1609         return 1;
1610       }
1611       if (n >= 7) {
1612         curve2d2 = DrawTrSurf::GetCurve2d(a[5]); 
1613         surface2 = DrawTrSurf::GetSurface(a[6]);
1614         if (curve2d2.IsNull() || surface2.IsNull()) {
1615           shift = 5;
1616           Case = 4;
1617         }
1618         else {
1619 // approx 2 curves_on_surfaces
1620           shift = 7;
1621           Case = 5;
1622         }
1623       }
1624       else {
1625         shift = 5;
1626         Case = 4;
1627       }
1628     }
1629   }
1630   else {
1631 // aproximation without reparamitrization
1632     if ( n>7 || n<3) return 1;
1633     shift = 3;
1634     curve = DrawTrSurf::GetCurve(a[2]);
1635     if (curve.IsNull()) {
1636       curve2d = DrawTrSurf::GetCurve2d(a[2]); 
1637       if (curve2d.IsNull()) {
1638         return 1;
1639       }
1640       Case = 2;
1641     }
1642     else
1643       Case = 1;
1644   }
1645   
1646   if (n>shift) Tol = Max(Draw::Atof(a[shift]),1.e-10);
1647   
1648   if (n>shift+1) {
1649     if (Draw::Atoi(a[shift+1]) == 0) Continuity = GeomAbs_C0;
1650     if (Draw::Atoi(a[shift+1]) == 2) Continuity = GeomAbs_C2;
1651   }
1652   
1653   if (n>shift+2) {
1654       MaxDeg = Draw::Atoi(a[shift+2]);
1655       if (MaxDeg<1 || MaxDeg>14) MaxDeg = 14;
1656     }
1657   
1658   if (n>shift+3) MaxSeg = Draw::Atoi(a[shift+3]);
1659     
1660   if (Case == 1) {
1661     GeomConvert_ApproxCurve appr(curve, Tol, Continuity, MaxSeg, MaxDeg);
1662     if(appr.HasResult()) {
1663       //appr.Dump(cout);
1664       Standard_SStream aSStream;
1665       appr.Dump(aSStream);
1666       di << aSStream;
1667       Handle(Geom_BSplineCurve) BSCurve = appr.Curve(); 
1668       DrawTrSurf::Set(a[1], BSCurve);
1669     }
1670  }   
1671
1672   else if (Case == 2) {
1673     Geom2dConvert_ApproxCurve appr(curve2d, Tol, Continuity, MaxSeg, MaxDeg);
1674     if(appr.HasResult()) {
1675       //appr.Dump(cout);
1676       Standard_SStream aSStream;
1677       appr.Dump(aSStream);
1678       di << aSStream;
1679       Handle(Geom2d_BSplineCurve) BSCurve = appr.Curve(); 
1680       DrawTrSurf::Set(a[1], BSCurve);
1681     }
1682   }    
1683
1684   else if (Case == 3) {
1685     Handle(Adaptor3d_HCurve) HACur = new GeomAdaptor_HCurve(curve);
1686     Approx_CurvilinearParameter appr(HACur, Tol, Continuity, MaxDeg, MaxSeg);
1687     if(appr.HasResult()) {
1688       //appr.Dump(cout);
1689       Standard_SStream aSStream;
1690       appr.Dump(aSStream);
1691       di << aSStream;
1692       Handle(Geom_BSplineCurve) BSCurve = appr.Curve3d(); 
1693       DrawTrSurf::Set(a[2], BSCurve);
1694     }
1695 }    
1696   else if (Case == 4) {
1697     Handle(Adaptor2d_HCurve2d) HACur2d = new Geom2dAdaptor_HCurve(curve2d);
1698     Handle(Adaptor3d_HSurface) HASur = new GeomAdaptor_HSurface(surface);
1699     Approx_CurvilinearParameter appr(HACur2d, HASur, Tol, Continuity, MaxDeg, MaxSeg);
1700     if(appr.HasResult()) {
1701       //appr.Dump(cout);
1702       Standard_SStream aSStream;
1703       appr.Dump(aSStream);
1704       di << aSStream;
1705       Handle(Geom_BSplineCurve) BSCurve = appr.Curve3d(); 
1706       DrawTrSurf::Set(a[2], BSCurve);
1707     }
1708   }
1709
1710   else if (Case == 5) {
1711     Handle(Adaptor2d_HCurve2d) HACur2d = new Geom2dAdaptor_HCurve(curve2d);
1712     Handle(Adaptor3d_HSurface) HASur = new GeomAdaptor_HSurface(surface);
1713     Handle(Adaptor2d_HCurve2d) HACur2d2 = new Geom2dAdaptor_HCurve(curve2d2);
1714     Handle(Adaptor3d_HSurface) HASur2 = new GeomAdaptor_HSurface(surface2);
1715     Approx_CurvilinearParameter appr(HACur2d, HASur, HACur2d2, HASur2, Tol, Continuity, MaxDeg, MaxSeg);
1716     if(appr.HasResult()) {
1717       //appr.Dump(cout);
1718       Standard_SStream aSStream;
1719       appr.Dump(aSStream);
1720       di << aSStream;
1721       Handle(Geom_BSplineCurve) BSCurve = appr.Curve3d(); 
1722       DrawTrSurf::Set(a[2], BSCurve);
1723     }
1724   }
1725   
1726
1727   return 0;
1728 }
1729
1730
1731 //=======================================================================
1732 //function : fitcurve
1733 //purpose  : 
1734 //=======================================================================
1735
1736 static Standard_Integer fitcurve(Draw_Interpretor& di, Standard_Integer n, const char** a)
1737 {
1738   if (n<3) return 1;
1739
1740   Handle(Geom_Curve) GC;
1741   GC = DrawTrSurf::GetCurve(a[2]);
1742   if (GC.IsNull())
1743     return 1;
1744
1745   Standard_Integer Dmin = 3;
1746   Standard_Integer Dmax = 14;
1747   Standard_Real Tol3d = 1.e-5;
1748   Standard_Boolean inverse = Standard_True;
1749
1750   if (n > 3)
1751   {
1752     Tol3d = Atof(a[3]);
1753   }
1754
1755   if (n > 4)
1756   {
1757     Dmax = atoi(a[4]);
1758   }
1759
1760   if (n > 5)
1761   {
1762     Standard_Integer inv = atoi(a[5]);
1763     if (inv > 0)
1764     {
1765       inverse = Standard_True;
1766     }
1767     else
1768     {
1769       inverse = Standard_False;
1770     }
1771   }
1772
1773   Handle(GeomAdaptor_HCurve) aGAC = new GeomAdaptor_HCurve(GC);
1774
1775   CurveEvaluator aCE(aGAC);
1776
1777   Approx_FitAndDivide anAppro(Dmin, Dmax, Tol3d, 0., Standard_True);
1778   anAppro.SetInvOrder(inverse);
1779   anAppro.Perform(aCE);
1780
1781   if (!anAppro.IsAllApproximated())
1782   {
1783     di << "Approximation failed \n";
1784     return 1;
1785   }
1786   Standard_Integer i;
1787   Standard_Integer NbCurves = anAppro.NbMultiCurves();
1788
1789   Convert_CompBezierCurvesToBSplineCurve Conv;
1790
1791   Standard_Real tol3d, tol2d, tolreached = 0.;
1792   for (i = 1; i <= NbCurves; i++) {
1793     anAppro.Error(i, tol3d, tol2d);
1794     tolreached = Max(tolreached, tol3d);
1795     AppParCurves_MultiCurve MC = anAppro.Value(i);
1796     TColgp_Array1OfPnt Poles(1, MC.Degree() + 1);
1797     MC.Curve(1, Poles);
1798     Conv.AddCurve(Poles);
1799   }
1800   Conv.Perform();
1801   Standard_Integer NbPoles = Conv.NbPoles();
1802   Standard_Integer NbKnots = Conv.NbKnots();
1803
1804   TColgp_Array1OfPnt      NewPoles(1, NbPoles);
1805   TColStd_Array1OfReal    NewKnots(1, NbKnots);
1806   TColStd_Array1OfInteger NewMults(1, NbKnots);
1807
1808   Conv.KnotsAndMults(NewKnots, NewMults);
1809   Conv.Poles(NewPoles);
1810
1811   BSplCLib::Reparametrize(GC->FirstParameter(),
1812     GC->LastParameter(),
1813     NewKnots);
1814   Handle(Geom_BSplineCurve) TheCurve = new Geom_BSplineCurve(NewPoles, NewKnots, NewMults, Conv.Degree());
1815
1816   DrawTrSurf::Set(a[1], TheCurve);
1817   di << a[1] << ": tolreached = " << tolreached << "\n";
1818
1819   return 0;
1820
1821 }
1822
1823 //=======================================================================
1824 //function : newbspline
1825 //purpose  : reduce the multiplicity of the knots to their minimum 
1826 //           compared to the degree of the curve
1827 //=======================================================================
1828
1829 static Standard_Integer splitc1(Draw_Interpretor& di,
1830                                    Standard_Integer n, const char** c)
1831
1832 {Standard_Real      tolerance=1.0e-5,
1833    angular_tolerance = 1.0e-4 ;
1834  Standard_Integer   optiontab,i;
1835  char name[100];
1836
1837  if (n<3) return 1;
1838  optiontab=Draw::Atoi(c[2]);
1839  if (n >= 4 )
1840    tolerance=Draw::Atof(c[3]);
1841  if (n >= 5) {
1842    angular_tolerance = Draw::Atof(c[4]) ;
1843  }
1844  Handle(Geom_Curve) ACurve = Handle(Geom_Curve)::DownCast(DrawTrSurf::Get(c[1])) ;
1845  
1846  Standard_Real f = ACurve->FirstParameter();
1847  Standard_Real l = ACurve->LastParameter();
1848
1849  if ( Precision::IsInfinite(f) || Precision::IsInfinite(l)) {
1850    di << " Error: Infinite curves\n";
1851    return 1;
1852  }
1853
1854  Handle(Geom_BSplineCurve) BS = GeomConvert::CurveToBSplineCurve(ACurve);
1855  
1856  if ( BS.IsNull()) return 1;
1857
1858  if (optiontab){
1859    Handle(TColGeom_HArray1OfBSplineCurve)  tabBS;
1860    GeomConvert::C0BSplineToArrayOfC1BSplineCurve(BS,
1861                                                  tabBS,
1862                                                  angular_tolerance,
1863                                                  tolerance);
1864    for (i=0;i<=(tabBS->Length()-1);i++){
1865      Sprintf(name,"%s_%d",c[1],i+1);
1866      Standard_CString new_name = name ;
1867      DrawTrSurf::Set(new_name,
1868                      tabBS->Value(i));
1869      di.AppendElement(name);
1870    }
1871  }
1872  else{
1873    GeomConvert::C0BSplineToC1BSplineCurve(BS,
1874                                           tolerance,
1875                                           angular_tolerance) ;
1876
1877    DrawTrSurf::Set(c[1],BS);
1878  }
1879  return 0;
1880 }
1881
1882 //=======================================================================
1883 //function : splitc12d
1884 //purpose  : reduce the multiplicity of the knots to their minimum 
1885 //           compared to the degree of the curve
1886 //=======================================================================
1887
1888 static Standard_Integer splitc12d(Draw_Interpretor& di,
1889                                      Standard_Integer n, const char** c)
1890
1891 {Standard_Real      tolerance=1.0e-5,
1892    angular_tolerance = 1.0e-4 ;
1893  Standard_Integer   optiontab,i;
1894  char name[100];
1895
1896  if (n<3) return 1;
1897  optiontab=Draw::Atoi(c[2]);
1898  if (n==4)
1899    tolerance=Draw::Atof(c[3]);
1900  if (n==5) 
1901    angular_tolerance = Draw::Atof(c[4]) ;
1902  Handle(Geom2d_Curve) ACurve = DrawTrSurf::GetCurve2d(c[1]);
1903  
1904  Standard_Real f = ACurve->FirstParameter();
1905  Standard_Real l = ACurve->LastParameter();
1906
1907  if ( Precision::IsInfinite(f) || Precision::IsInfinite(l)) {
1908    di << " Error: Infinite curves\n";
1909    return 1;
1910  }
1911
1912  Handle(Geom2d_BSplineCurve) BS = Geom2dConvert::CurveToBSplineCurve(ACurve);
1913  
1914  if ( BS.IsNull()) return 1;
1915
1916  if (optiontab){
1917    Handle(TColGeom2d_HArray1OfBSplineCurve)  tabBS;
1918    Geom2dConvert::C0BSplineToArrayOfC1BSplineCurve(BS,
1919                                                    tabBS,
1920                                                    angular_tolerance,
1921                                                    tolerance);
1922    for (i=0;i<=(tabBS->Length()-1);i++){
1923      Sprintf(name,"%s_%d",c[1],i+1);
1924      Standard_CString new_name = name ;
1925      DrawTrSurf::Set(new_name,
1926                      tabBS->Value(i));
1927      di.AppendElement(name);
1928    }
1929  }
1930  else{
1931    Geom2dConvert::C0BSplineToC1BSplineCurve(BS,tolerance);
1932    DrawTrSurf::Set(c[1],BS);
1933  }
1934  return 0;
1935 }
1936
1937 //=======================================================================
1938 //function : canceldenom
1939 //purpose  : set the value of the denominator cancel its first 
1940 //           derivative on the boundaries of the surface if possible
1941 //=======================================================================
1942
1943 static Standard_Integer canceldenom(Draw_Interpretor& ,
1944                                      Standard_Integer n, const char** c)
1945
1946 {Standard_Integer    uoption,voption;
1947  Standard_Boolean    udirection=Standard_False;
1948  Standard_Boolean    vdirection=Standard_False;
1949  if (n<4) return 1;
1950  uoption=Draw::Atoi(c[2]);
1951  voption=Draw::Atoi(c[3]);
1952  if (uoption)
1953    udirection=Standard_True;
1954  if (voption)
1955    vdirection=Standard_True;
1956  Handle(Geom_BSplineSurface) BSurf = DrawTrSurf::GetBSplineSurface(c[1]);
1957  GeomLib::CancelDenominatorDerivative(BSurf,udirection,vdirection);
1958  DrawTrSurf::Set(c[1],BSurf);
1959  return 0;
1960 }
1961
1962 //=======================================================================
1963 //function : length
1964 //purpose  : eval curve's length
1965 //=======================================================================
1966
1967 static Standard_Integer length(Draw_Interpretor& di,
1968                                Standard_Integer n, const char** a)
1969 {
1970   if (n<2) return 1;
1971   Handle(Geom_Curve) GC = DrawTrSurf::GetCurve(a[1]);
1972   Handle(Geom2d_Curve) GC2d = DrawTrSurf::GetCurve2d(a[1]);
1973   Standard_Real Tol = Precision::Confusion(), L;
1974   if (n==3) Tol = Draw::Atof(a[2]);
1975
1976   if (!GC.IsNull()) {
1977     GeomAdaptor_Curve AC(GC);
1978     L = GCPnts_AbscissaPoint::Length(AC, Tol);
1979   }  
1980   else if (!GC2d.IsNull()) {
1981     Geom2dAdaptor_Curve AC(GC2d);
1982     L = GCPnts_AbscissaPoint::Length(AC, Tol);
1983   }
1984   else {
1985     di << a[1] << "is not a curve\n";
1986     return 1;
1987   }
1988
1989   di << "The length " << a[1] << " is " << L << "\n";
1990   return 0;
1991 }
1992
1993
1994
1995 //=======================================================================
1996 //function : CurveCommands
1997 //purpose  : 
1998 //=======================================================================
1999
2000 void  GeomliteTest::CurveCommands(Draw_Interpretor& theCommands)
2001 {
2002   
2003   static Standard_Boolean loaded = Standard_False;
2004   if (loaded) return;
2005   loaded = Standard_True;
2006   
2007   DrawTrSurf::BasicCommands(theCommands);
2008   
2009   const char* g;
2010   
2011   
2012   // analytic curves
2013   g = "GEOMETRY curves creation";
2014
2015
2016   theCommands.Add("point",
2017                   "point name x y [z]",
2018                   __FILE__,
2019                   point ,g);
2020   
2021   theCommands.Add("line",
2022                   "line name pos dir",
2023                   __FILE__,
2024                   anacurve,g);
2025   
2026   theCommands.Add("circle",
2027                   "circle name x y [z [dx dy dz]] [ux uy [uz]] radius",
2028                   __FILE__,
2029                   anacurve,g);
2030   
2031   theCommands.Add("ellipse",
2032                   "ellipse name x y [z [dx dy dz]] [ux uy [uz]] major minor",
2033                   __FILE__,
2034                   anacurve,g);
2035   theCommands.Add("parabola",
2036                   "parabola name x y [z [dx dy dz]] [ux uy [uz]] focal",
2037                   __FILE__,
2038                   anacurve,g);
2039   theCommands.Add("hyperbola",
2040                   "hyperbola name x y [z [dx dy dz]] [ux uy [uz]] major minor",
2041                   __FILE__,
2042                   anacurve,g);
2043
2044   theCommands.Add("beziercurve",
2045                   "beziercurve name nbpole pole, [weight]",
2046                   __FILE__,
2047                   polecurve,g);
2048
2049   theCommands.Add("bsplinecurve",
2050                   "bsplinecurve name degree nbknots  knot, umult  pole, weight",
2051                   __FILE__,
2052                   polecurve,g);
2053
2054   theCommands.Add("pbsplinecurve",
2055                   "pbsplinecurve name degree nbknots  knot, umult  pole, weight (periodic)",
2056                   __FILE__,
2057                   polecurve,g);
2058
2059   theCommands.Add("2dbeziercurve",
2060                   "2dbeziercurve name nbpole pole, [weight]",
2061                   __FILE__,
2062                   polecurve2d,g);
2063
2064   theCommands.Add("2dbsplinecurve",
2065                   "2dbsplinecurve name degree nbknots  knot, umult  pole, weight",
2066                   __FILE__,
2067                   polecurve2d,g);
2068
2069   theCommands.Add("2dpbsplinecurve",
2070                   "2dpbsplinecurve name degree nbknots  knot, umult  pole, weight (periodic)",
2071                   __FILE__,
2072                   polecurve2d,g);
2073
2074   g = "GEOMETRY Curves and Surfaces modification";
2075
2076   theCommands.Add("reverse",
2077                   "reverse name ... ",
2078                   __FILE__,
2079                   reverse,g);
2080
2081   theCommands.Add("cmovep",
2082                   "cmovep name index dx dy dz",
2083                   __FILE__,
2084                   cmovepole,g);
2085
2086   theCommands.Add("cmovepoint",
2087                   "cmovepoint name u dx dy [dz index1 index2]",
2088                   __FILE__,
2089                   cmovepoint,g);
2090
2091   theCommands.Add("cmovetangent",
2092                   "cmovetangent name u  x y [z] tx ty [tz constraint = 0]",
2093                   __FILE__,
2094                   cmovetangent,g) ;
2095
2096   theCommands.Add("insertknot",
2097                   "insertknot name knot [mult = 1] [knot mult ...]",
2098                   __FILE__,
2099                   cinsertknot,g);
2100
2101   theCommands.Add("setknot",
2102                   "setknot name index knot [mult]",
2103                   __FILE__,
2104                   csetknot,g);
2105
2106   theCommands.Add("remknot",
2107                   "remknot name index [mult] [tol]",
2108                   __FILE__,
2109                   cremknot,g);
2110
2111   theCommands.Add("incdeg",
2112                   "incdeg name degree",
2113                   __FILE__,
2114                   increasedegree,g);
2115
2116   theCommands.Add("rempole",
2117                   "rempole name index",
2118                   __FILE__,
2119                   removepole,g);
2120
2121   theCommands.Add("insertpole",
2122                   "insertpole name index x y [z] [weight]",
2123                   __FILE__,
2124                   insertpole,g);
2125
2126   theCommands.Add("cfindp",
2127                   "cfindp name view x y index",
2128                   __FILE__,
2129                   cfindp,g);
2130
2131   theCommands.Add("setperiodic",
2132                   "setperiodic name ...",
2133                   __FILE__,
2134                   csetperiodic,g);
2135
2136   theCommands.Add("setnotperiodic",
2137                   "setnotperiodic name",
2138                   __FILE__,
2139                   csetperiodic,g);
2140
2141   theCommands.Add("segment",
2142                   "segment name Ufirst Ulast [tol]",
2143                    __FILE__,
2144                   segment , g);
2145
2146   theCommands.Add("setorigin",
2147                   "setorigin name knotindex",
2148                    __FILE__,
2149                   setorigin , g);
2150
2151   g = "GEOMETRY curves and surfaces analysis";
2152
2153   theCommands.Add("cvalue",
2154                   "cvalue curvename U  X Y Z [D1X D1Y D1Z D2X D2Y D2Z]",
2155                   __FILE__,
2156                   value,g);
2157
2158   theCommands.Add("2dcvalue",
2159                   "2dcvalue curvename U  X Y [D1X D1Y D2X D2Y]",
2160                   __FILE__,
2161                   value2d,g);
2162
2163   theCommands.Add("coord",
2164                   "coord P x y [z]: set in x y [z] the coordinates of P",
2165                   __FILE__,
2166                   coord,g);
2167
2168   theCommands.Add("minmaxcurandinf",
2169                   "minmaxcurandinf curve",
2170                   __FILE__,
2171                   minmaxcurandinf,g);
2172   
2173   theCommands.Add("shcurvature",
2174                   "shcurvature curvename",
2175                   __FILE__,
2176                   shcurvature,g);
2177
2178   theCommands.Add("clcurvature",
2179                   "clcurvature curvename",
2180                   __FILE__,
2181                   clcurvature,g);
2182   
2183
2184  theCommands.Add("radiusmax",
2185                   "radiusmax curvename  radius",
2186                   __FILE__,
2187                   radiusmax,g);
2188
2189  theCommands.Add("radiusratio",
2190                   "radiusratio curvename ratio",
2191                   __FILE__,
2192                   radiusratio,g); 
2193   theCommands.Add("localprop",
2194                   "localprop curvename U",
2195                   __FILE__,
2196                   localprop,g);
2197   theCommands.Add("rawcont",
2198                   "rawcont curve1 curve2 u1 u2",
2199                   __FILE__,
2200                   rawcont,g) ;
2201   theCommands.Add("approxcurve",
2202                   "approxcurve [-L] name curve1 [Surf1] [curve2d2 Surf2] [Tol [cont [maxdeg [maxseg]]]] ",
2203                   __FILE__,
2204                   approxcurve,g);
2205
2206   theCommands.Add("approxcurveonsurf",
2207                   "approxcurveonsurf name curve2d surface [Tol [cont [maxdeg [maxseg]]]] ",
2208                   __FILE__,
2209                   approxcurveonsurf,g);
2210
2211  theCommands.Add("fitcurve", "fitcurve result  curve [tol [maxdeg [inverse]]]", __FILE__, fitcurve, g);
2212
2213  theCommands.Add("length", "length curve [Tol]", 
2214                   __FILE__,
2215                   length, g);
2216
2217
2218   theCommands.Add("splitc1",
2219                   "splitc1 bspline resultinarray(0/1) [tol] [angtol] ",
2220                   __FILE__,
2221                   splitc1,g);
2222
2223   theCommands.Add("splitc12d",
2224                   "splitc12d bspline2d resultinarray(0/1) [tol] [angtol] ",
2225                   __FILE__,
2226                   splitc12d,g);
2227   theCommands.Add("canceldenom",
2228                   "canceldenom BSpline-Surface UDirection(0/1) VDirection(0/1)",
2229                   __FILE__,
2230                   canceldenom,g);
2231
2232  
2233
2234 }