0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / Approx / Approx_BSplComputeLine.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <stdio.h>
16
17 #include <Approx_ParametrizationType.hxx>
18 #include <TColStd_Array1OfReal.hxx>
19 #include <TColgp_Array1OfPnt.hxx>
20 #include <TColgp_Array1OfPnt2d.hxx>
21 #include <gp_Pnt.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <gp_Vec.hxx>
24 #include <gp_Vec2d.hxx>
25 #include <TColgp_Array1OfVec.hxx>
26 #include <TColgp_Array1OfVec2d.hxx>
27 #include <AppParCurves_Constraint.hxx>
28 #include <AppParCurves_HArray1OfConstraintCouple.hxx>
29 #include <AppParCurves_MultiPoint.hxx>
30 #include <Precision.hxx>
31 #include <math_IntegerVector.hxx>
32 #include <math_Gauss.hxx>
33 #include <math_Uzawa.hxx>
34 #include <AppParCurves_ConstraintCouple.hxx>
35 #include Approx_BSpParLeastSquareOfMyBSplGradient_hxx
36
37 #if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
38
39 static Standard_Boolean mydebug = Standard_False;
40
41 #include <Draw.hxx>
42 #include <Draw_Appli.hxx>
43 #include <DrawTrSurf.hxx>
44 #include <Draw_Text2D.hxx>
45 #include <Draw_Text3D.hxx>
46 #include <TColStd_Array1OfInteger.hxx>
47 #include <Geom_BSplineCurve.hxx>
48 #include <Geom2d_BSplineCurve.hxx>
49 #include <Geom_Line.hxx>
50 #include <Geom2d_Line.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom2d_TrimmedCurve.hxx>
53
54
55 static void DUMP(const MultiLine& Line)
56 {
57   Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
58   firstP = LineTool::FirstPoint(Line);
59   lastP = LineTool::LastPoint(Line);
60
61   nbP3d = LineTool::NbP3d(Line);
62   nbP2d = LineTool::NbP2d(Line);
63   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
64   if (nbP3d == 0) mynbP3d = 1;
65   if (nbP2d == 0) mynbP2d = 1;
66
67   TColgp_Array1OfPnt tabP(1, mynbP3d);
68   TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
69   TColgp_Array1OfVec TabV(1, mynbP3d);
70   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
71   Standard_Boolean Ok;
72   Handle(Geom_Line) L3d;
73   Handle(Geom2d_Line) L2d;
74   Handle(Geom_TrimmedCurve) L3dt;
75   Handle(Geom2d_TrimmedCurve) L2dt;
76   Handle(Draw_Text2D) T2D;
77   Handle(Draw_Text3D) T3D;
78
79   char solname[100];
80   char mytext[10];
81
82   for (i = firstP; i <= lastP; i++) {
83     if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
84     else if (nbP2d != 0)          LineTool::Value(Line, i, tabP2d);
85     else if (nbP3d != 0)          LineTool::Value(Line, i, tabP);
86
87     for (j = 1; j <= nbP3d; j++) {
88       sprintf(solname, "%s%i%s_%i", "p", j, "3d", i);
89       char* Temp = solname;
90       DrawTrSurf::Set(Temp, tabP(j));
91       //      DrawTrSurf::Set(solname, tabP(j));
92       if (i == firstP || i == lastP) {
93         sprintf(mytext, "%s%i", " ", i);
94         T3D = new Draw_Text3D(tabP(j), mytext, Draw_vert);
95         dout << T3D;
96       }
97     }
98     for (j = 1; j <= nbP2d; j++) {
99       sprintf(solname, "%s%i%s_%i", "p", j, "2d", i);
100       char* Temp = solname;
101       DrawTrSurf::Set(Temp, tabP2d(j));
102       //      DrawTrSurf::Set(solname, tabP2d(j));
103       if (i == firstP || i == lastP) {
104         sprintf(mytext, "%s%i", " ", i);
105         T2D = new Draw_Text2D(tabP2d(j), mytext, Draw_vert);
106         dout << T2D;
107       }
108     }
109
110     // le cas des tangentes aux extremites:
111     if (i == firstP || i == lastP) {
112       if (nbP3d != 0 && nbP2d != 0)
113         Ok = LineTool::Tangency(Line, i, TabV, TabV2d);
114       else if (nbP2d != 0)
115         Ok = LineTool::Tangency(Line, i, TabV2d);
116       else if (nbP3d != 0)
117         Ok = LineTool::Tangency(Line, i, TabV);
118
119       if (Ok) {
120         for (j = 1; j <= nbP3d; j++) {
121           sprintf(solname, "%s%i%s_%i", "t", j, "3d", i);
122           L3d = new Geom_Line(tabP(j), gp_Dir(TabV(j)));
123           L3dt = new Geom_TrimmedCurve(L3d, 0.0, 0.3);
124           char* Temp = solname;
125           DrawTrSurf::Set(Temp, L3dt);
126           //      DrawTrSurf::Set(solname, L3dt);
127         }
128         for (j = 1; j <= nbP2d; j++) {
129           sprintf(solname, "%s%i%s_%i", "t", j, "2d", i);
130           L2d = new Geom2d_Line(tabP2d(j), gp_Dir2d(TabV2d(j)));
131           L2dt = new Geom2d_TrimmedCurve(L2d, 0.0, 0.3);
132           char* Temp = solname;
133           DrawTrSurf::Set(Temp, L2dt);
134           //      DrawTrSurf::Set(solname, L2dt);
135         }
136       }
137     }
138   }
139   dout.Flush();
140 }
141
142
143 static void DUMP(const AppParCurves_MultiBSpCurve& C)
144 {
145   static Standard_Integer nbappel = 0;
146   Standard_Integer i, j, nbP2d, nbP3d;
147   Standard_Integer nbpoles = C.NbPoles();
148   Standard_Integer deg = C.Degree();
149   const TColStd_Array1OfReal& Knots = C.Knots();
150   const TColStd_Array1OfInteger& Mults = C.Multiplicities();
151
152   Handle(Geom_BSplineCurve) BSp;
153   Handle(Geom2d_BSplineCurve) BSp2d;
154
155   TColgp_Array1OfPnt tabPoles(1, nbpoles);
156   TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
157   char solname[100];
158
159   nbappel++;
160   for (i = 1; i <= C.NbCurves(); i++) {
161     if (C.Dimension(i) == 3) {
162       C.Curve(i, tabPoles);
163       BSp = new Geom_BSplineCurve(tabPoles, Knots, Mults, deg);
164       sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
165       char* Temp = solname;
166       DrawTrSurf::Set(Temp, BSp);
167       //      DrawTrSurf::Set(solname, BSp);
168     }
169     else {
170       C.Curve(i, tabPoles2d);
171       BSp2d = new Geom2d_BSplineCurve(tabPoles2d, Knots, Mults, deg);
172       sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
173       char* Temp = solname;
174       DrawTrSurf::Set(Temp, BSp2d);
175       //      DrawTrSurf::Set(solname, BSp2d);
176     }
177   }
178   dout.Flush();
179 }
180
181
182 #endif
183
184
185
186
187 //=======================================================================
188 //function : FirstTangencyVector
189 //purpose  : 
190 //=======================================================================
191 void Approx_BSplComputeLine::FirstTangencyVector(const MultiLine&  Line,
192   const Standard_Integer index,
193   math_Vector&           V)
194   const {
195
196   Standard_Integer i, j, nbP2d, nbP3d;
197   nbP3d = LineTool::NbP3d(Line);
198   nbP2d = LineTool::NbP2d(Line);
199   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
200   if (nbP3d == 0) mynbP3d = 1;
201   if (nbP2d == 0) mynbP2d = 1;
202   Standard_Boolean Ok = Standard_False;
203   TColgp_Array1OfVec TabV(1, mynbP3d);
204   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
205
206   if (nbP3d != 0 && nbP2d != 0)
207     Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
208   else if (nbP2d != 0)
209     Ok = LineTool::Tangency(Line, index, TabV2d);
210   else if (nbP3d != 0)
211     Ok = LineTool::Tangency(Line, index, TabV);
212
213   if (Ok) {
214     if (nbP3d != 0) {
215       j = 1;
216       for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
217         V(j) = TabV(i).X();
218         V(j + 1) = TabV(i).Y();
219         V(j + 2) = TabV(i).Z();
220         j += 3;
221       }
222     }
223     if (nbP2d != 0) {
224       j = nbP3d * 3 + 1;
225       for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
226         V(j) = TabV2d(i).X();
227         V(j + 1) = TabV2d(i).Y();
228         j += 2;
229       }
230     }
231   }
232   else {
233
234     // recherche d un vecteur tangent par construction d une parabole:
235     AppParCurves_Constraint firstC, lastC;
236     firstC = lastC = AppParCurves_PassPoint;
237     Standard_Integer nbpoles = 3;
238     math_Vector mypar(index, index + 2);
239     Parameters(Line, index, index + 2, mypar);
240     Approx_BSpParLeastSquareOfMyBSplGradient
241       LSQ(Line, index, index + 2, firstC, lastC, mypar, nbpoles);
242     AppParCurves_MultiCurve C = LSQ.BezierValue();
243
244     gp_Pnt myP;
245     gp_Vec myV;
246     gp_Pnt2d myP2d;
247     gp_Vec2d myV2d;
248     j = 1;
249     for (i = 1; i <= nbP3d; i++) {
250       C.D1(i, 0.0, myP, myV);
251       V(j) = myV.X();
252       V(j + 1) = myV.Y();
253       V(j + 2) = myV.Z();
254       j += 3;
255     }
256     j = nbP3d * 3 + 1;
257     for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
258       C.D1(i, 0.0, myP2d, myV2d);
259       V(j) = myV2d.X();
260       V(j + 1) = myV2d.Y();
261       j += 2;
262     }
263   }
264
265 }
266
267
268 //=======================================================================
269 //function : LastTangencyVector
270 //purpose  : 
271 //=======================================================================
272 void Approx_BSplComputeLine::LastTangencyVector(const MultiLine&       Line,
273   const Standard_Integer index,
274   math_Vector&           V)
275   const {
276   Standard_Integer i, j, nbP2d, nbP3d;
277   nbP3d = LineTool::NbP3d(Line);
278   nbP2d = LineTool::NbP2d(Line);
279   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
280   if (nbP3d == 0) mynbP3d = 1;
281   if (nbP2d == 0) mynbP2d = 1;
282   Standard_Boolean Ok = Standard_False;
283   TColgp_Array1OfVec TabV(1, mynbP3d);
284   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
285
286
287   if (nbP3d != 0 && nbP2d != 0)
288     Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
289   else if (nbP2d != 0)
290     Ok = LineTool::Tangency(Line, index, TabV2d);
291   else if (nbP3d != 0)
292     Ok = LineTool::Tangency(Line, index, TabV);
293
294   if (Ok) {
295     if (nbP3d != 0) {
296       j = 1;
297       for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
298         V(j) = TabV(i).X();
299         V(j + 1) = TabV(i).Y();
300         V(j + 2) = TabV(i).Z();
301         j += 3;
302       }
303     }
304     if (nbP2d != 0) {
305       j = nbP3d * 3 + 1;
306       for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
307         V(j) = TabV2d(i).X();
308         V(j + 1) = TabV2d(i).Y();
309         j += 2;
310       }
311     }
312   }
313   else {
314
315     // recherche d un vecteur tangent par construction d une parabole:
316     AppParCurves_Constraint firstC, lastC;
317     firstC = lastC = AppParCurves_PassPoint;
318     Standard_Integer nbpoles = 3;
319     math_Vector mypar(index - 2, index);
320     Parameters(Line, index - 2, index, mypar);
321     Approx_BSpParLeastSquareOfMyBSplGradient
322       LSQ(Line, index - 2, index, firstC, lastC, mypar, nbpoles);
323     AppParCurves_MultiCurve C = LSQ.BezierValue();
324
325     gp_Pnt myP;
326     gp_Vec myV;
327     gp_Pnt2d myP2d;
328     gp_Vec2d myV2d;
329     j = 1;
330     for (i = 1; i <= nbP3d; i++) {
331       C.D1(i, 1.0, myP, myV);
332       V(j) = myV.X();
333       V(j + 1) = myV.Y();
334       V(j + 2) = myV.Z();
335       j += 3;
336     }
337     j = nbP3d * 3 + 1;
338     for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
339       C.D1(i, 1.0, myP2d, myV2d);
340       V(j) = myV2d.X();
341       V(j + 1) = myV2d.Y();
342       j += 2;
343     }
344   }
345
346 }
347
348
349
350 //=======================================================================
351 //function : SearchFirstLambda
352 //purpose  : 
353 //=======================================================================
354 Standard_Real Approx_BSplComputeLine::
355 SearchFirstLambda(const MultiLine&            Line,
356   const math_Vector&          aPar,
357   const TColStd_Array1OfReal& Theknots,
358   const math_Vector&          V,
359   const Standard_Integer      index) const {
360
361   // dq/dw = lambda* V = (p2-p1)/(u2-u1)
362
363   Standard_Integer nbP2d, nbP3d;
364   gp_Pnt P1, P2;
365   gp_Pnt2d P12d, P22d;
366   nbP3d = LineTool::NbP3d(Line);
367   nbP2d = LineTool::NbP2d(Line);
368   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
369   if (nbP3d == 0) mynbP3d = 1;
370   if (nbP2d == 0) mynbP2d = 1;
371   TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
372   TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
373
374
375   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
376   else if (nbP2d != 0)          LineTool::Value(Line, index, tabP12d);
377   else if (nbP3d != 0)          LineTool::Value(Line, index, tabP1);
378
379   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index + 1, tabP2, tabP22d);
380   else if (nbP2d != 0)          LineTool::Value(Line, index + 1, tabP22d);
381   else if (nbP3d != 0)          LineTool::Value(Line, index + 1, tabP2);
382
383
384   Standard_Real U1 = aPar(index), U2 = aPar(index + 1);
385   Standard_Real lambda, S;
386   Standard_Integer low = V.Lower();
387   Standard_Integer nbknots = Theknots.Length();
388
389   if (nbP3d != 0) {
390     P1 = tabP1(1);
391     P2 = tabP2(1);
392     gp_Vec P1P2(P1, P2), myV;
393     myV.SetCoord(V(low), V(low + 1), V(low + 2));
394     lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
395     S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
396   }
397   else {
398     P12d = tabP12d(1);
399     P22d = tabP22d(1);
400     gp_Vec2d P1P2(P12d, P22d), myV;
401     myV.SetCoord(V(low), V(low + 1));
402     lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
403     S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
404   }
405   return ((S*lambda)*(Theknots(2) - Theknots(1)) / (Theknots(nbknots) - Theknots(1)));
406
407 }
408
409
410 //=======================================================================
411 //function : SearchLastLambda
412 //purpose  : 
413 //=======================================================================
414 Standard_Real Approx_BSplComputeLine::
415 SearchLastLambda(const MultiLine&            Line,
416   const math_Vector&          aPar,
417   const TColStd_Array1OfReal& Theknots,
418   const math_Vector&          V,
419   const Standard_Integer      index) const
420
421 {
422   // dq/dw = lambda* V = (p2-p1)/(u2-u1)
423
424   Standard_Integer nbP2d, nbP3d;
425   gp_Pnt P1, P2;
426   gp_Pnt2d P12d, P22d;
427   nbP3d = LineTool::NbP3d(Line);
428   nbP2d = LineTool::NbP2d(Line);
429   Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
430   if (nbP3d == 0) mynbP3d = 1;
431   if (nbP2d == 0) mynbP2d = 1;
432   TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
433   TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
434
435   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index - 1, tabP, tabP2d);
436   else if (nbP2d != 0)          LineTool::Value(Line, index - 1, tabP2d);
437   else if (nbP3d != 0)          LineTool::Value(Line, index - 1, tabP);
438
439   if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
440   else if (nbP2d != 0)          LineTool::Value(Line, index, tabP22d);
441   else if (nbP3d != 0)          LineTool::Value(Line, index, tabP2);
442
443
444   Standard_Real U1 = aPar(index - 1), U2 = aPar(index);
445   Standard_Real lambda, S;
446   Standard_Integer low = V.Lower();
447   Standard_Integer nbknots = Theknots.Length();
448   if (nbP3d != 0) {
449     P1 = tabP(1);
450     P2 = tabP2(1);
451     gp_Vec P1P2(P1, P2), myV;
452     myV.SetCoord(V(low), V(low + 1), V(low + 2));
453     lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
454     S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
455   }
456   else {
457     P12d = tabP2d(1);
458     P22d = tabP22d(1);
459     gp_Vec2d P1P2(P12d, P22d), myV;
460     myV.SetCoord(V(low), V(low + 1));
461     lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
462     S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
463   }
464
465   return ((S*lambda)*(Theknots(nbknots) - Theknots(nbknots - 1))
466     / (Theknots(nbknots) - Theknots(1)));
467 }
468
469
470
471 //=======================================================================
472 //function : Approx_BSplComputeLine
473 //purpose  : 
474 //=======================================================================
475 Approx_BSplComputeLine::Approx_BSplComputeLine
476 (const MultiLine& Line,
477   const math_Vector& Parameters,
478   const Standard_Integer degreemin,
479   const Standard_Integer degreemax,
480   const Standard_Real Tolerance3d,
481   const Standard_Real Tolerance2d,
482   const Standard_Integer NbIterations,
483   const Standard_Boolean cutting,
484   const Standard_Boolean Squares)
485 {
486   myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
487     Parameters.Upper());
488   for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
489     myfirstParam->SetValue(i, Parameters(i));
490   }
491   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
492   Par = Approx_IsoParametric;
493   myPeriodic = Standard_False;
494   mydegremin = degreemin;
495   mydegremax = degreemax;
496   mytol3d = Tolerance3d;
497   mytol2d = Tolerance2d;
498   mysquares = Squares;
499   mycut = cutting;
500   myitermax = NbIterations;
501   alldone = Standard_False;
502   mycont = -1;
503   myfirstC = AppParCurves_TangencyPoint;
504   mylastC = AppParCurves_TangencyPoint;
505   myhasknots = Standard_False;
506   myhasmults = Standard_False;
507   currenttol3d = currenttol2d = RealLast();
508   tolreached = Standard_False;
509   Perform(Line);
510 }
511
512
513 //=======================================================================
514 //function : Approx_BSplComputeLine
515 //purpose  : 
516 //=======================================================================
517 Approx_BSplComputeLine::Approx_BSplComputeLine
518 (const math_Vector& Parameters,
519   const Standard_Integer degreemin,
520   const Standard_Integer degreemax,
521   const Standard_Real Tolerance3d,
522   const Standard_Real Tolerance2d,
523   const Standard_Integer NbIterations,
524   const Standard_Boolean cutting,
525   const Standard_Boolean Squares)
526 {
527   myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
528     Parameters.Upper());
529   for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
530     myfirstParam->SetValue(i, Parameters(i));
531   }
532   myfirstC = AppParCurves_TangencyPoint;
533   mylastC = AppParCurves_TangencyPoint;
534   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
535   Par = Approx_IsoParametric;
536   myPeriodic = Standard_False;
537   mydegremin = degreemin;
538   mydegremax = degreemax;
539   mytol3d = Tolerance3d;
540   mytol2d = Tolerance2d;
541   mysquares = Squares;
542   mycut = cutting;
543   myitermax = NbIterations;
544   alldone = Standard_False;
545   myhasknots = Standard_False;
546   myhasmults = Standard_False;
547   mycont = -1;
548   currenttol3d = currenttol2d = RealLast();
549   tolreached = Standard_False;
550 }
551
552 //=======================================================================
553 //function : Approx_BSplComputeLine
554 //purpose  : 
555 //=======================================================================
556 Approx_BSplComputeLine::Approx_BSplComputeLine
557 (const Standard_Integer degreemin,
558   const Standard_Integer degreemax,
559   const Standard_Real Tolerance3d,
560   const Standard_Real Tolerance2d,
561   const Standard_Integer NbIterations,
562   const Standard_Boolean cutting,
563   const Approx_ParametrizationType parametrization,
564   const Standard_Boolean Squares)
565 {
566   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
567   Par = parametrization;
568   myPeriodic = Standard_False;
569   mydegremin = degreemin;
570   mydegremax = degreemax;
571   mytol3d = Tolerance3d;
572   mytol2d = Tolerance2d;
573   mysquares = Squares;
574   mycut = cutting;
575   myitermax = NbIterations;
576   myfirstC = AppParCurves_TangencyPoint;
577   mylastC = AppParCurves_TangencyPoint;
578   alldone = Standard_False;
579   myhasknots = Standard_False;
580   myhasmults = Standard_False;
581   mycont = -1;
582   currenttol3d = currenttol2d = RealLast();
583   tolreached = Standard_False;
584 }
585
586
587 //=======================================================================
588 //function : Approx_BSplComputeLine
589 //purpose  : 
590 //=======================================================================
591 Approx_BSplComputeLine::Approx_BSplComputeLine
592 (const MultiLine& Line,
593   const Standard_Integer degreemin,
594   const Standard_Integer degreemax,
595   const Standard_Real Tolerance3d,
596   const Standard_Real Tolerance2d,
597   const Standard_Integer NbIterations,
598   const Standard_Boolean cutting,
599   const Approx_ParametrizationType parametrization,
600   const Standard_Boolean Squares)
601 {
602   myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
603   alldone = Standard_False;
604   mydegremin = degreemin;
605   mydegremax = degreemax;
606   mytol3d = Tolerance3d;
607   mytol2d = Tolerance2d;
608   mysquares = Squares;
609   mycut = cutting;
610   myitermax = NbIterations;
611   Par = parametrization;
612   myPeriodic = Standard_False;
613   myfirstC = AppParCurves_TangencyPoint;
614   mylastC = AppParCurves_TangencyPoint;
615   myhasknots = Standard_False;
616   myhasmults = Standard_False;
617   mycont = -1;
618   currenttol3d = currenttol2d = RealLast();
619   tolreached = Standard_False;
620   Perform(Line);
621 }
622
623
624
625 //=======================================================================
626 //function : Perform
627 //purpose  : 
628 //=======================================================================
629 void Approx_BSplComputeLine::Perform(const MultiLine& Line)
630 {
631
632 #if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
633   if (mydebug) DUMP(Line);
634 #endif
635
636   Standard_Integer i, Thefirstpt, Thelastpt;
637   Standard_Boolean Finish = Standard_False, begin = Standard_True;
638
639   // recherche des vraies contraintes donnees par la Line:
640   FindRealConstraints(Line);
641
642   Thefirstpt = LineTool::FirstPoint(Line);
643   Thelastpt = LineTool::LastPoint(Line);
644   Standard_Integer myfirstpt = Thefirstpt;
645   Standard_Integer mylastpt = Thelastpt;
646
647   AppParCurves_ConstraintCouple myCouple1(myfirstpt, realfirstC);
648   AppParCurves_ConstraintCouple myCouple2(mylastpt, reallastC);
649   myConstraints->SetValue(1, myCouple1);
650   myConstraints->SetValue(2, myCouple2);
651
652   math_Vector TheParam(Thefirstpt, Thelastpt, 0.0);
653   if (myfirstParam.IsNull()) {
654     Parameters(Line, Thefirstpt, Thelastpt, TheParam);
655   }
656   else {
657     for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
658       TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i);
659     }
660   }
661
662   myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper());
663   for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) {
664     myParameters->SetValue(i, TheParam(i));
665   }
666   Standard_Integer nbknots = 2;
667   Standard_Real l;
668   alldone = Standard_False;
669
670   if (!mycut) {
671
672     // cas ou on ne desire pas de noeuds supplementaires.
673     // ==================================================
674
675     if (!myhasknots) {
676       TColStd_Array1OfReal theknots(1, 2);
677       TColStd_Array1OfInteger themults(1, 2);
678       theknots(1) = 0.0;
679       theknots(2) = 1.0;
680       alldone = Compute(Line, myfirstpt, mylastpt, TheParam, theknots, themults);
681     }
682     else {
683       if (!myhasmults) {
684         TColStd_Array1OfInteger themults(1, myknots->Length());
685         alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
686           myknots->Array1(), themults);
687       }
688       else {
689         alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
690           myknots->Array1(), mymults->ChangeArray1());
691       }
692     }
693   }
694   else {
695
696     // cas ou on va iterer a partir de noeuds donnes par l''utilisateur 
697     // ou a partir d''une bezier.
698     // ================================================================
699
700     while (!Finish) {
701
702       currenttol3d = currenttol2d = RealLast();
703
704       if (myhasknots && begin) {
705
706         if (!myhasmults) {
707
708           // 1er cas: l''utilisateur donne des noeuds de depart mais
709           // a nous de fixer  les multiplicites  en  fonction  de  la 
710           // continuite desiree.
711           // ========================================================
712
713           TColStd_Array1OfInteger TheMults(1, myknots->Length());
714           alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
715             myknots->Array1(), TheMults);
716         }
717         else {
718
719           // 2eme cas: l''utilisateur donne des noeuds de depart 
720           // avec leurs multiplicites.
721           // ===================================================
722
723           alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
724             myknots->Array1(), mymults->ChangeArray1());
725         }
726         begin = Standard_False;
727       }
728
729       else {
730
731         // 3eme cas: l''utilisateur ne donne aucun noeuds de depart
732         // ========================================================
733
734         TColStd_Array1OfReal Theknots(1, nbknots);
735         TColStd_Array1OfInteger TheMults(1, nbknots);
736         Theknots(1) = 0.0;
737         Theknots(nbknots) = 1.0;
738         for (i = 2; i <= nbknots - 1; i++) {
739
740           l = (mylastpt - myfirstpt)*Standard_Real(i - 1)
741             / Standard_Real(nbknots - 1);
742           Standard_Integer ll = (Standard_Integer)(l);
743           Standard_Real a = l - ll;
744           Standard_Real p1 = TheParam(ll + myfirstpt);
745           Standard_Real p2 = TheParam(ll + 1 + myfirstpt);
746           Theknots(i) = (1. - a)*p1 + a*p2;
747         }
748
749         alldone = Compute(Line, myfirstpt, mylastpt, TheParam, Theknots, TheMults);
750
751       }
752
753       if (!alldone) nbknots++;
754       else Finish = Standard_True;
755     }
756   }
757
758 #if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
759   if (mydebug) DUMP(TheMultiBSpCurve);
760 #endif
761
762 }
763
764
765
766
767 //=======================================================================
768 //function : Parameters
769 //purpose  : 
770 //=======================================================================
771 const TColStd_Array1OfReal& Approx_BSplComputeLine::Parameters() const
772 {
773   return myParameters->Array1();
774 }
775
776
777
778 //=======================================================================
779 //function : Value
780 //purpose  : 
781 //=======================================================================
782 const AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::Value() const
783 {
784   return TheMultiBSpCurve;
785 }
786
787 //=======================================================================
788 //function : ChangeValue
789 //purpose  : 
790 //=======================================================================
791 AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::ChangeValue()
792 {
793   return TheMultiBSpCurve;
794 }
795
796 //=======================================================================
797 //function : Parameters
798 //purpose  : 
799 //=======================================================================
800
801 void Approx_BSplComputeLine::Parameters(const MultiLine& Line,
802   const Standard_Integer firstP,
803   const Standard_Integer lastP,
804   math_Vector& TheParameters) const
805 {
806   Standard_Integer i, j, nbP2d, nbP3d;
807   Standard_Real dist;
808   const Standard_Integer aNbp = lastP - firstP + 1;
809
810
811   if (aNbp == 2) {
812     TheParameters(firstP) = 0.0;
813     TheParameters(lastP) = 1.0;
814   }
815   else if (Par == Approx_ChordLength || Par == Approx_Centripetal)
816   {
817     nbP3d = LineTool::NbP3d(Line);
818     nbP2d = LineTool::NbP2d(Line);
819     Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
820     if (nbP3d == 0) mynbP3d = 1;
821     if (nbP2d == 0) mynbP2d = 1;
822
823     TheParameters(firstP) = 0.0;
824     dist = 0.0;
825     TColgp_Array1OfPnt tabP(1, mynbP3d);
826     TColgp_Array1OfPnt tabPP(1, mynbP3d);
827     TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
828     TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
829
830     for (i = firstP + 1; i <= lastP; i++)
831     {
832       if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i - 1, tabP, tabP2d);
833       else if (nbP2d != 0)          LineTool::Value(Line, i - 1, tabP2d);
834       else if (nbP3d != 0)          LineTool::Value(Line, i - 1, tabP);
835
836       if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
837       else if (nbP2d != 0)          LineTool::Value(Line, i, tabPP2d);
838       else if (nbP3d != 0)          LineTool::Value(Line, i, tabPP);
839       dist = 0.0;
840       for (j = 1; j <= nbP3d; j++)
841       {
842         const gp_Pnt &aP1 = tabP(j),
843           &aP2 = tabPP(j);
844         dist += aP2.SquareDistance(aP1);
845       }
846       for (j = 1; j <= nbP2d; j++)
847       {
848         const gp_Pnt2d &aP12d = tabP2d(j),
849           &aP22d = tabPP2d(j);
850
851         dist += aP22d.SquareDistance(aP12d);
852       }
853
854       dist = Sqrt(dist);
855       if (Par == Approx_ChordLength)
856       {
857         TheParameters(i) = TheParameters(i - 1) + dist;
858       }
859       else
860       {// Par == Approx_Centripetal
861         TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
862       }
863     }
864     for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
865   }
866   else {
867     for (i = firstP; i <= lastP; i++) {
868       TheParameters(i) = (Standard_Real(i) - firstP) /
869         (Standard_Real(lastP - Standard_Real(firstP)));
870     }
871   }
872 }
873
874
875 //=======================================================================
876 //function : Compute
877 //purpose  : 
878 //=======================================================================
879 Standard_Boolean Approx_BSplComputeLine::Compute(const MultiLine& Line,
880   const Standard_Integer fpt,
881   const Standard_Integer lpt,
882   math_Vector&     Para,
883   const TColStd_Array1OfReal& Knots,
884   TColStd_Array1OfInteger& Mults)
885 {
886   Standard_Integer i, deg, nbpoles, multinter;
887   Standard_Boolean mydone;
888   Standard_Real Fv, TheTol3d, TheTol2d, l1, l2;
889   Standard_Integer nbp = lpt - fpt + 1;
890   mylambda1 = 0.0;
891   mylambda2 = 0.0;
892
893   math_Vector aParams(Para.Lower(), Para.Upper());
894
895   for (deg = mydegremin; deg <= mydegremax; deg++) {
896
897     aParams = Para;
898
899     if (!myhasmults) {
900       Mults(Mults.Lower()) = deg + 1;
901       Mults(Mults.Upper()) = deg + 1;
902       nbpoles = deg + 1;
903       if (mycont == -1) multinter = 1;
904       else multinter = Max(1, deg - mycont);
905       for (i = Mults.Lower() + 1; i <= Mults.Upper() - 1; i++) {
906         Mults(i) = multinter;
907         nbpoles += multinter;
908       }
909     }
910     else {
911       nbpoles = -deg - 1;
912       for (i = Mults.Lower(); i <= Mults.Upper(); i++) {
913         nbpoles += Mults.Value(i);
914       }
915     }
916
917     Standard_Integer nbpolestocompare = nbpoles;
918     if (realfirstC == AppParCurves_TangencyPoint) nbpolestocompare++;
919     if (reallastC == AppParCurves_TangencyPoint) nbpolestocompare++;
920     if (realfirstC == AppParCurves_CurvaturePoint) nbpolestocompare++;
921     if (reallastC == AppParCurves_CurvaturePoint) nbpolestocompare++;
922     if (nbpolestocompare > nbp) {
923       Interpol(Line);
924       tolreached = Standard_True;
925       return Standard_True;
926     }
927
928     AppParCurves_MultiBSpCurve mySCU(nbpoles);
929
930     if (mysquares) {
931       Approx_BSpParLeastSquareOfMyBSplGradient SQ(Line, Knots, Mults, fpt, lpt,
932         realfirstC, reallastC, aParams, nbpoles);
933       mydone = SQ.IsDone();
934       if (mydone) {
935         mySCU = SQ.BSplineValue();
936         SQ.Error(Fv, TheTol3d, TheTol2d);
937       }
938       else continue;
939     }
940     else {
941       if (nbpoles != deg + 1) {
942
943         if (deg == mydegremin && (realfirstC >= AppParCurves_TangencyPoint ||
944           reallastC >= AppParCurves_TangencyPoint)) {
945           Approx_BSpParLeastSquareOfMyBSplGradient
946             thefitt(Line, Knots, Mults, fpt, lpt, realfirstC, reallastC, aParams, nbpoles);
947           mylambda1 = thefitt.FirstLambda()*deg;
948           mylambda2 = thefitt.LastLambda()*deg;
949
950         }
951         l1 = mylambda1 / deg;
952         l2 = mylambda2 / deg;
953
954         Approx_MyBSplGradient GRAD(Line, fpt, lpt, myConstraints,
955           aParams, Knots, Mults, deg, mytol3d,
956           mytol2d, myitermax, l1, l2);
957
958         mydone = GRAD.IsDone();
959         if (mydone) {
960           mySCU = GRAD.Value();
961           TheTol3d = GRAD.MaxError3d();
962           TheTol2d = GRAD.MaxError2d();
963         }
964         else continue;
965       }
966       else {
967         Approx_MyGradientbis GRAD2(Line, fpt, lpt, myConstraints,
968           aParams, deg, mytol3d,
969           mytol2d, myitermax);
970         mydone = GRAD2.IsDone();
971         if (mydone) {
972           if (GRAD2.Value().NbCurves() == 0)
973             continue;
974           mySCU = AppParCurves_MultiBSpCurve(GRAD2.Value(), Knots, Mults);
975           TheTol3d = GRAD2.MaxError3d();
976           TheTol2d = GRAD2.MaxError2d();
977         }
978         else continue;
979       }
980     }
981     Standard_Boolean save = Standard_True;
982
983     for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
984       if (aParams(i) <= -0.000001 || aParams(i) >= 1.000001) {
985         save = Standard_False;
986         break;
987       }
988     }
989
990     if (mydone) {
991       if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
992         // Stockage de la multicurve approximee.
993         tolreached = Standard_True;
994         TheMultiBSpCurve = mySCU;
995         currenttol3d = TheTol3d;
996         currenttol2d = TheTol2d;
997         if (save) {
998           for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
999             myParameters->SetValue(i, aParams(i));
1000           }
1001         }
1002         return Standard_True;
1003       }
1004     }
1005
1006     if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
1007       TheMultiBSpCurve = mySCU;
1008       currenttol3d = TheTol3d;
1009       currenttol2d = TheTol2d;
1010       if (save) {
1011         for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
1012           myParameters->SetValue(i, aParams(i));
1013         }
1014       }
1015     }
1016
1017   }
1018
1019   return Standard_False;
1020 }
1021
1022
1023
1024 //=======================================================================
1025 //function : SetParameters
1026 //purpose  : 
1027 //=======================================================================
1028 void Approx_BSplComputeLine::SetParameters(const math_Vector& ThePar)
1029 {
1030   myfirstParam = new TColStd_HArray1OfReal(ThePar.Lower(),
1031     ThePar.Upper());
1032   for (Standard_Integer i = ThePar.Lower(); i <= ThePar.Upper(); i++) {
1033     myfirstParam->SetValue(i, ThePar(i));
1034   }
1035 }
1036
1037
1038 //=======================================================================
1039 //function : SetKnots
1040 //purpose  : 
1041 //=======================================================================
1042 void Approx_BSplComputeLine::SetKnots(const TColStd_Array1OfReal& Knots)
1043 {
1044   myhasknots = Standard_True;
1045   myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper());
1046   for (Standard_Integer i = Knots.Lower(); i <= Knots.Upper(); i++) {
1047     myknots->SetValue(i, Knots(i));
1048   }
1049 }
1050
1051
1052 //=======================================================================
1053 //function : SetKnotsAndMultiplicities
1054 //purpose  : 
1055 //=======================================================================
1056 void Approx_BSplComputeLine::SetKnotsAndMultiplicities
1057 (const TColStd_Array1OfReal&    Knots,
1058   const TColStd_Array1OfInteger& Mults)
1059 {
1060   myhasknots = Standard_True;
1061   myhasmults = Standard_True;
1062   Standard_Integer i;
1063   myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper());
1064   for (i = Knots.Lower(); i <= Knots.Upper(); i++) {
1065     myknots->SetValue(i, Knots(i));
1066   }
1067   mymults = new TColStd_HArray1OfInteger(Mults.Lower(), Mults.Upper());
1068   for (i = Mults.Lower(); i <= Mults.Upper(); i++) {
1069     mymults->SetValue(i, Mults(i));
1070   }
1071 }
1072
1073 //=======================================================================
1074 //function : Init
1075 //purpose  : 
1076 //=======================================================================
1077 void Approx_BSplComputeLine::Init(const Standard_Integer degreemin,
1078   const Standard_Integer degreemax,
1079   const Standard_Real Tolerance3d,
1080   const Standard_Real Tolerance2d,
1081   const Standard_Integer NbIterations,
1082   const Standard_Boolean cutting,
1083   const Approx_ParametrizationType parametrization,
1084   const Standard_Boolean Squares)
1085 {
1086   mydegremin = degreemin;
1087   mydegremax = degreemax;
1088   mytol3d = Tolerance3d;
1089   mytol2d = Tolerance2d;
1090   Par = parametrization;
1091   mysquares = Squares;
1092   mycut = cutting;
1093   myitermax = NbIterations;
1094 }
1095
1096
1097
1098 //=======================================================================
1099 //function : SetDegrees
1100 //purpose  : 
1101 //=======================================================================
1102 void Approx_BSplComputeLine::SetDegrees(const Standard_Integer degreemin,
1103   const Standard_Integer degreemax)
1104 {
1105   mydegremin = degreemin;
1106   mydegremax = degreemax;
1107 }
1108
1109
1110 //=======================================================================
1111 //function : SetTolerances
1112 //purpose  : 
1113 //=======================================================================
1114 void Approx_BSplComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1115   const Standard_Real Tolerance2d)
1116 {
1117   mytol3d = Tolerance3d;
1118   mytol2d = Tolerance2d;
1119 }
1120
1121
1122 //=======================================================================
1123 //function : SetConstraints
1124 //purpose  : 
1125 //=======================================================================
1126 void Approx_BSplComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1127   const AppParCurves_Constraint LastC)
1128 {
1129   myfirstC = FirstC;
1130   mylastC = LastC;
1131 }
1132
1133 //=======================================================================
1134 //function : SetPeriodic
1135 //purpose  : 
1136 //=======================================================================
1137 void Approx_BSplComputeLine::SetPeriodic(const Standard_Boolean thePeriodic)
1138 {
1139   myPeriodic = thePeriodic;
1140 }
1141
1142
1143 //=======================================================================
1144 //function : IsAllApproximated
1145 //purpose  : 
1146 //=======================================================================
1147 Standard_Boolean Approx_BSplComputeLine::IsAllApproximated() const
1148 {
1149   return alldone;
1150 }
1151
1152 //=======================================================================
1153 //function : IsToleranceReached
1154 //purpose  : 
1155 //=======================================================================
1156 Standard_Boolean Approx_BSplComputeLine::IsToleranceReached() const
1157 {
1158   return tolreached;
1159 }
1160
1161 //=======================================================================
1162 //function : Error
1163 //purpose  : 
1164 //=======================================================================
1165 void Approx_BSplComputeLine::Error(Standard_Real& tol3d,
1166   Standard_Real& tol2d) const
1167 {
1168   tol3d = currenttol3d;
1169   tol2d = currenttol2d;
1170 }
1171
1172
1173
1174 //=======================================================================
1175 //function : SetContinuity
1176 //purpose  : 
1177 //=======================================================================
1178 void Approx_BSplComputeLine::SetContinuity(const Standard_Integer C)
1179 {
1180   mycont = C;
1181 }
1182
1183
1184
1185 //=======================================================================
1186 //function : FindRealConstraints
1187 //purpose  : 
1188 //=======================================================================
1189 void Approx_BSplComputeLine::FindRealConstraints(const MultiLine& Line)
1190 {
1191   realfirstC = myfirstC;
1192   reallastC = mylastC;
1193   Standard_Integer nbP2d, nbP3d;
1194   nbP3d = LineTool::NbP3d(Line);
1195   nbP2d = LineTool::NbP2d(Line);
1196   Standard_Boolean Ok = Standard_False;
1197   TColgp_Array1OfVec TabV(1, Max(1, nbP3d));
1198   TColgp_Array1OfVec2d TabV2d(1, Max(1, nbP2d));
1199   Standard_Integer Thefirstpt = LineTool::FirstPoint(Line);
1200   Standard_Integer Thelastpt = LineTool::LastPoint(Line);
1201
1202   if (myfirstC >= AppParCurves_TangencyPoint) {
1203
1204     if (nbP3d != 0 && nbP2d != 0)
1205       Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d);
1206     else if (nbP2d != 0)
1207       Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d);
1208     else if (nbP3d != 0)
1209       Ok = LineTool::Tangency(Line, Thefirstpt, TabV);
1210
1211     realfirstC = AppParCurves_PassPoint;
1212     if (Ok) {
1213       realfirstC = AppParCurves_TangencyPoint;
1214       if (myfirstC == AppParCurves_CurvaturePoint) {
1215         if (nbP3d != 0 && nbP2d != 0)
1216           Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d);
1217         else if (nbP2d != 0)
1218           Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d);
1219         else if (nbP3d != 0)
1220           Ok = LineTool::Tangency(Line, Thefirstpt, TabV);
1221         if (Ok) {
1222           realfirstC = AppParCurves_CurvaturePoint;
1223         }
1224       }
1225     }
1226   }
1227
1228
1229   if (mylastC >= AppParCurves_TangencyPoint) {
1230
1231     if (nbP3d != 0 && nbP2d != 0)
1232       Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d);
1233     else if (nbP2d != 0)
1234       Ok = LineTool::Tangency(Line, Thelastpt, TabV2d);
1235     else if (nbP3d != 0)
1236       Ok = LineTool::Tangency(Line, Thelastpt, TabV);
1237
1238     reallastC = AppParCurves_PassPoint;
1239     if (Ok) {
1240       reallastC = AppParCurves_TangencyPoint;
1241       if (mylastC == AppParCurves_CurvaturePoint) {
1242         if (nbP3d != 0 && nbP2d != 0)
1243           Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d);
1244         else if (nbP2d != 0)
1245           Ok = LineTool::Tangency(Line, Thelastpt, TabV2d);
1246         else if (nbP3d != 0)
1247           Ok = LineTool::Tangency(Line, Thelastpt, TabV);
1248         if (Ok) {
1249           reallastC = AppParCurves_CurvaturePoint;
1250         }
1251       }
1252     }
1253   }
1254
1255 }
1256
1257
1258
1259
1260 //=======================================================================
1261 //function : Interpol
1262 //purpose  : 
1263 //=======================================================================
1264 void Approx_BSplComputeLine::Interpol(const MultiLine& Line)
1265 {
1266   Standard_Integer i, Thefirstpt, Thelastpt, deg = 3;
1267   mycont = 2;
1268   Thefirstpt = LineTool::FirstPoint(Line);
1269   Thelastpt = LineTool::LastPoint(Line);
1270   math_Vector TheParam(Thefirstpt, Thelastpt, 0.0);
1271   //Par = Approx_ChordLength;
1272   if (myfirstParam.IsNull()) {
1273     Parameters(Line, Thefirstpt, Thelastpt, TheParam);
1274   }
1275   else {
1276     for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
1277       TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i);
1278     }
1279   }
1280   AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1281   Standard_Real lambda1, lambda2;
1282   Standard_Real Fv;
1283
1284   // Recherche du nombre de noeuds.
1285   Standard_Integer nbknots, nbpoles, nbpoints;
1286   nbpoints = Thelastpt - Thefirstpt + 1;
1287
1288   if (nbpoints == 2) {
1289     Cons = AppParCurves_NoConstraint;
1290     Standard_Integer mydeg = 1;
1291     Approx_BSpParLeastSquareOfMyBSplGradient
1292       LSQ(Line, Thefirstpt, Thelastpt, Cons, Cons, TheParam, mydeg + 1);
1293     alldone = LSQ.IsDone();
1294     TColStd_Array1OfReal TheKnots(1, 2);
1295     TColStd_Array1OfInteger TheMults(1, 2);
1296     TheKnots(1) = TheParam(Thefirstpt);  TheKnots(2) = TheParam(Thelastpt);
1297     TheMults(1) = TheMults(2) = mydeg + 1;
1298     TheMultiBSpCurve =
1299       AppParCurves_MultiBSpCurve(LSQ.BezierValue(), TheKnots, TheMults);
1300     LSQ.Error(Fv, currenttol3d, currenttol2d);
1301
1302   }
1303   else {
1304     nbpoles = nbpoints + 2;
1305     nbknots = nbpoints;
1306
1307     // Resolution:
1308     TColStd_Array1OfReal Theknots(1, nbknots);
1309     Theknots(1) = TheParam(Thefirstpt);
1310     Theknots(nbknots) = TheParam(Thelastpt);
1311     TColStd_Array1OfInteger TheMults(1, nbknots);
1312     TheMults(1) = deg + 1;
1313     TheMults(nbknots) = deg + 1;
1314
1315     Standard_Integer low = TheParam.Lower();
1316     for (i = 2; i <= nbknots - 1; i++) {
1317       Theknots(i) = TheParam(i + low - 1);
1318       TheMults(i) = 1;
1319     }
1320
1321
1322     Standard_Integer nbP = 3 * LineTool::NbP3d(Line) + 2 * LineTool::NbP2d(Line);
1323     math_Vector V1(1, nbP), V2(1, nbP);
1324
1325     if (nbpoints == 3 || nbpoints == 4) {
1326       FirstTangencyVector(Line, Thefirstpt, V1);
1327       lambda1 = SearchFirstLambda(Line, TheParam, Theknots, V1, Thefirstpt);
1328
1329       LastTangencyVector(Line, Thelastpt, V2);
1330       lambda2 = SearchLastLambda(Line, TheParam, Theknots, V2, Thelastpt);
1331
1332       lambda1 = lambda1 / deg;
1333       lambda2 = lambda2 / deg;
1334     }
1335     else {
1336       Standard_Integer nnpol, nnp = Min(nbpoints, 9);
1337       nnpol = nnp;
1338       Standard_Integer lastp = Min(Thelastpt, Thefirstpt + nnp - 1);
1339       Standard_Real U;
1340       Approx_BSpParLeastSquareOfMyBSplGradient
1341         SQ1(Line, Thefirstpt, lastp, Cons, Cons, nnpol);
1342
1343       math_Vector P1(Thefirstpt, lastp);
1344       for (i = Thefirstpt; i <= lastp; i++) P1(i) = TheParam(i);
1345       SQ1.Perform(P1);
1346       const AppParCurves_MultiCurve& C1 = SQ1.BezierValue();
1347       U = 0.0;
1348       TangencyVector(Line, C1, U, V1);
1349
1350       Standard_Integer firstp = Max(Thefirstpt, Thelastpt - nnp + 1);
1351
1352       if (firstp == Thefirstpt && lastp == Thelastpt) {
1353         U = 1.0;
1354         TangencyVector(Line, C1, U, V2);
1355       }
1356       else {
1357         Approx_BSpParLeastSquareOfMyBSplGradient
1358           SQ2(Line, firstp, Thelastpt, Cons, Cons, nnpol);
1359
1360         math_Vector P2(firstp, Thelastpt);
1361         for (i = firstp; i <= Thelastpt; i++) P2(i) = TheParam(i);
1362         SQ2.Perform(P2);
1363         const AppParCurves_MultiCurve& C2 = SQ2.BezierValue();
1364         U = 1.0;
1365         TangencyVector(Line, C2, U, V2);
1366       }
1367
1368     
1369       lambda1 = 1. / deg;
1370       lambda1 = lambda1*(Theknots(2) - Theknots(1))
1371         / (Theknots(nbknots) - Theknots(1));
1372       lambda2 = 1. / deg;
1373       lambda2 = lambda2*(Theknots(nbknots) - Theknots(nbknots - 1))
1374         / (Theknots(nbknots) - Theknots(1));
1375
1376     }
1377
1378     if (myPeriodic)
1379     {
1380       V1 = 0.5 * (V1 + V2);
1381       V2 = V1;
1382     }
1383
1384     Approx_BSpParLeastSquareOfMyBSplGradient
1385       SQ(Line, Theknots, TheMults, Thefirstpt, Thelastpt,
1386         Cons, Cons, nbpoles);
1387
1388     SQ.Perform(TheParam, V1, V2, lambda1, lambda2);
1389     alldone = SQ.IsDone();
1390     TheMultiBSpCurve = SQ.BSplineValue();
1391     SQ.Error(Fv, currenttol3d, currenttol2d);
1392     tolreached = Standard_True;
1393   }
1394   myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper());
1395   for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) {
1396     myParameters->SetValue(i, TheParam(i));
1397   }
1398 }
1399
1400
1401 //=======================================================================
1402 //function : TangencyVector
1403 //purpose  : 
1404 //=======================================================================
1405 void Approx_BSplComputeLine::TangencyVector(
1406   const MultiLine&               Line,
1407   const AppParCurves_MultiCurve& C,
1408   const Standard_Real            U,
1409   math_Vector&                   V) const
1410 {
1411
1412   Standard_Integer i, j, nbP2d, nbP3d;
1413   nbP3d = LineTool::NbP3d(Line);
1414   nbP2d = LineTool::NbP2d(Line);
1415
1416   gp_Pnt myP;
1417   gp_Vec myV;
1418   gp_Pnt2d myP2d;
1419   gp_Vec2d myV2d;
1420   j = 1;
1421   for (i = 1; i <= nbP3d; i++) {
1422     C.D1(i, U, myP, myV);
1423     V(j) = myV.X();
1424     V(j + 1) = myV.Y();
1425     V(j + 2) = myV.Z();
1426     j += 3;
1427   }
1428   j = nbP3d * 3 + 1;
1429   for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
1430     C.D1(i, U, myP2d, myV2d);
1431     V(j) = myV2d.X();
1432     V(j + 1) = myV2d.Y();
1433     j += 2;
1434   }
1435
1436 }
1437