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
39static 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
55static 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
143static 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//=======================================================================
191void 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//=======================================================================
272void 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//=======================================================================
354Standard_Real Approx_BSplComputeLine::
355SearchFirstLambda(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//=======================================================================
414Standard_Real Approx_BSplComputeLine::
415SearchLastLambda(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//=======================================================================
475Approx_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//=======================================================================
517Approx_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//=======================================================================
556Approx_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//=======================================================================
591Approx_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//=======================================================================
629void 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//=======================================================================
771const TColStd_Array1OfReal& Approx_BSplComputeLine::Parameters() const
772{
773  return myParameters->Array1();
774}
775
776
777
778//=======================================================================
779//function : Value
780//purpose  :
781//=======================================================================
782const AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::Value() const
783{
784  return TheMultiBSpCurve;
785}
786
787//=======================================================================
788//function : ChangeValue
789//purpose  :
790//=======================================================================
791AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::ChangeValue()
792{
793  return TheMultiBSpCurve;
794}
795
796//=======================================================================
797//function : Parameters
798//purpose  :
799//=======================================================================
800
801void 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//=======================================================================
879Standard_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//=======================================================================
1028void 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//=======================================================================
1042void 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//=======================================================================
1056void 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//=======================================================================
1077void 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//=======================================================================
1102void 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//=======================================================================
1114void 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//=======================================================================
1126void 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//=======================================================================
1137void Approx_BSplComputeLine::SetPeriodic(const Standard_Boolean thePeriodic)
1138{
1139  myPeriodic = thePeriodic;
1140}
1141
1142
1143//=======================================================================
1144//function : IsAllApproximated
1145//purpose  :
1146//=======================================================================
1147Standard_Boolean Approx_BSplComputeLine::IsAllApproximated() const
1148{
1149  return alldone;
1150}
1151
1152//=======================================================================
1153//function : IsToleranceReached
1154//purpose  :
1155//=======================================================================
1156Standard_Boolean Approx_BSplComputeLine::IsToleranceReached() const
1157{
1158  return tolreached;
1159}
1160
1161//=======================================================================
1162//function : Error
1163//purpose  :
1164//=======================================================================
1165void 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//=======================================================================
1178void Approx_BSplComputeLine::SetContinuity(const Standard_Integer C)
1179{
1180  mycont = C;
1181}
1182
1183
1184
1185//=======================================================================
1186//function : FindRealConstraints
1187//purpose  :
1188//=======================================================================
1189void 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//=======================================================================
1264void 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//=======================================================================
1405void 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
1438