Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cubicsplines.cpp
Go to the documentation of this file.
1 
3 #include <math.h>
4 #include <assert.h>
5 #include "cubicsplines.h"
7 {
8 #ifdef SPLINE_METHOD2
9  A = B = C = E = F = G = I = J = K = 0;
10  D = H = L = 1.0;
11 #else
12  memset( this, 0, sizeof (CubicSpline) );
13 #endif
14 }
15 #ifdef SPLINE_METHOD2
17 {
18  this->A = P3.i-3*P2.i+3*P1.i-P0.i;
19  this->B = 3*P2.i-6*P1.i+3*P0.i;
20  this->C = 3*P1.i-3*P0.i;
21  this->D = P0.i;
22 
23  this->E = P3.j-3*P2.j+3*P1.j-P0.j;
24  this->F = 3*P2.j-6*P1.j+3*P0.j;
25  this->G = 3*P1.j-3*P0.j;
26  this->H = P0.j;
27 
28  this->I = P3.k-3*P2.k+3*P1.k-P0.k;
29  this->J = 3*P2.k-6*P1.k+3*P0.k;
30  this->K = 3*P1.k-3*P0.k;
31  this->L = P0.k;
32 }
33 
35 {
36  QVector res( (A*t*t*t+B*t*t+C*t+D), (E*t*t*t+F*t*t+G*t+H), (I*t*t*t+J*t*t+K*t+L) );
37  return res;
38 }
39 
41 {}
42 #endif
43 
44 #ifdef SPLINE_METHOD1
45 //VECCholeskyTriDiagResol
46 //
47 double * VECCholeskyTriDiagResol( double *B, int nb )
48 {
49  double *Y;
50  double *LDiag;
51  double *LssDiag;
52  double *Result;
53  int I, K, Debut, Fin;
54 
55  Debut = 0;
56  Fin = nb-1;
57  //assert(Assigned(B));
58  LDiag = new double[nb];
59  LssDiag = new double[(nb-1)];
60  //try
61  LDiag[Debut] = 1.4142135; //= sqrt(2)
62  LssDiag[Debut] = 1.0/1.4142135;
63  for (K = Debut+1; K <= Fin-1; K++) {
64  LDiag[K] = sqrt( 4-LssDiag[K-1]*LssDiag[K-1] );
65  LssDiag[K] = 1.0/LDiag[K];
66  }
67  LDiag[Fin] = sqrt( 2-LssDiag[Fin-1]*LssDiag[Fin-1] );
68  Y = new double[nb];
69  //try
70  Y[Debut] = B[Debut]/LDiag[Debut];
71  for (I = Debut+1; I <= Fin; I++)
72  Y[I] = (B[I]-Y[I-1]*LssDiag[I-1])/LDiag[I];
73  Result = new double[nb];
74  assert( LDiag[Fin] != 0 );
75  Result[Fin] = Y[Fin]/LDiag[Fin];
76  for (I = Fin-1; I >= Debut; I--) {
77  assert( LDiag[I] != 0 );
78  Result[I] = (Y[I]-Result[I+1]*LssDiag[I])/LDiag[I];
79  }
80  //finally
81  delete[] Y;
82  //end;
83  //finally
84  delete[] LDiag;
85  delete[] LssDiag;
86  //end;
87 //end;
88  return Result;
89 }
90 
91 //MATInterpolationHermite
92 //
93 //double ** as return type ????????????????
94 double ** MATInterpolationHermite( double *ordonnees, int nb )
95 {
96  double a, b, c, d;
97  double **m;
98  int i, n;
99  double *bb;
100  double *deriv;
101  double *fa;
102 
103  m = 0;
104  if ( ordonnees != 0 && (nb > 0) ) {
105  n = nb-1;
106  bb = new double[nb];
107  //try
108  bb[0] = 3*(ordonnees[1]-ordonnees[0]);
109  bb[n] = 3*(ordonnees[n]-ordonnees[n-1]);
110  for (i = 1; i <= n-1; i++)
111  bb[i] = 3*(ordonnees[i+1]-ordonnees[i-1]);
112  deriv = VECCholeskyTriDiagResol( bb, nb );
113  //try
114  m = new double*[n];
115  for (i = 0; i <= n-1; i++) {
116  m[i] = new double[4];
117  a = ordonnees[i];
118  b = deriv[i];
119  c = 3*(ordonnees[i+1]-ordonnees[i])-2*deriv[i]-deriv[i+1];
120  d = -2*(ordonnees[i+1]-ordonnees[i])+deriv[i]+deriv[i+1];
121  fa = m[i];
122  fa[3] = a+i*(i*(c-i*d)-b);
123  fa[2] = b+i*(3*i*d-2*c);
124  fa[1] = c-3*i*d;
125  fa[0] = d;
126  }
127  //finally
128  delete[] deriv;
129  //end;
130  //finally
131  delete[] bb;
132  //end;
133  }
134  return m;
135 }
136 
137 //MATValeurSpline
138 //
139 double MATValeurSpline( double **spline, double x, int nb )
140 {
141  int i;
142  double *sa;
143  double res;
144  if (spline != 0) {
145  if (x <= 0)
146  i = 0;
147  else if (x > nb-1)
148  i = nb-1;
149  else i = (int) floor( x );
150  //TODO : the following line looks like a bug...
151  if ( i == (nb-1) ) i--;
152  sa = spline[i];
153  res = ( (sa[0]*x+sa[1])*x+sa[2] )*x+sa[3];
154  } else {res = 0; } return res;
155 }
156 
157 //MATValeurSplineSlope
158 //
159 double MATValeurSplineSlope( double **spline, double x, int nb )
160 {
161  int i;
162  double *sa;
163  double res;
164  if (spline != 0) {
165  if (x <= 0)
166  i = 0;
167  else if (x > nb-1)
168  i = nb-1;
169  else i = (int) floor( x );
170  //TODO : the following line looks like a bug...
171  if ( i == (nb-1) ) i--;
172  sa = spline[i];
173  res = (3*sa[0]*x+2*sa[1])*x+sa[2];
174  } else {res = 0; } return res;
175 }
176 
177 //------------------
178 //------------------ TCubicSpline ------------------
179 //------------------
180 
181 //Create
182 //
184 {
185  double X[4];
186  double Y[4];
187  double Z[4];
188  X[0] = P0.i;
189  X[1] = P1.i;
190  X[2] = P2.i;
191  X[3] = P3.i;
192  Y[0] = P0.j;
193  Y[1] = P1.j;
194  Y[2] = P2.j;
195  Y[3] = P3.j;
196  Z[0] = P0.k;
197  Z[1] = P1.k;
198  Z[2] = P2.k;
199  Z[3] = P3.k;
200  FNb = 4;
201  MatX = MATInterpolationHermite( X, FNb );
202  MatY = MATInterpolationHermite( Y, FNb );
203  MatZ = MATInterpolationHermite( Z, FNb );
204  MatW = 0;
205 }
206 
207 //Destroy
208 //
210 {
211  //Loop through all 4 matrices to delete elements
212  for (int i = 0; i < FNb-1; i++) {
213  delete MatX[i];
214  delete MatY[i];
215  delete MatZ[i];
216  if (MatW != 0)
217  delete MatW[i];
218  }
219  delete MatX;
220  delete MatY;
221  delete MatZ;
222  if (MatW != 0)
223  delete MatW;
224 }
225 
226 //SplineAffineVector
227 //
228 QVector CubicSpline::computePoint( double t ) const
229 {
230  return QVector( MATValeurSpline( MatX, t, FNb ), MATValeurSpline( MatY, t, FNb ), MATValeurSpline( MatZ, t, FNb ) );
231 }
232 
233 #endif
234 
235 #ifdef SPLINE_METHOD3
236 
237 /*
238  ********************** SPLINE STUFF ***********************
239  *** THIS ONE IS NOT IMPLEMENTED, THIS IS JUST RAW SOURCE **
240  *** THIS ONE IS NOT IMPLEMENTED, THIS IS JUST RAW SOURCE **
241  ********************** SPLINE STUFF ***********************
242  */
243 
244 /*
245  * This returns the point "output" on the spline curve.
246  * The parameter "v" indicates the position, it ranges from 0 to n-t+2
247  *
248  */
249 void SplinePoint( int *u, int n, int t, double v, XYZ *control, XYZ *output )
250 {
251  int k;
252  double b;
253 
254  output->x = 0;
255  output->y = 0;
256  output->z = 0;
257  for (k = 0; k <= n; k++) {
258  b = SplineBlend( k, t, u, v );
259  output->x += control[k].x*b;
260  output->y += control[k].y*b;
261  output->z += control[k].z*b;
262  }
263 }
264 
265 /*
266  * Calculate the blending value, this is done recursively.
267  *
268  * If the numerator and denominator are 0 the expression is 0.
269  * If the deonimator is 0 the expression is 0
270  */
271 double SplineBlend( int k, int t, int *u, double v )
272 {
273  double value;
274  if (t == 1) {
275  if ( (u[k] <= v) && (v < u[k+1]) )
276  value = 1;
277  else
278  value = 0;
279  } else {
280  if ( (u[k+t-1] == u[k]) && (u[k+t] == u[k+1]) )
281  value = 0;
282  else if (u[k+t-1] == u[k])
283  value = (u[k+t]-v)/(u[k+t]-u[k+1])*SplineBlend( k+1, t-1, u, v );
284  else if (u[k+t] == u[k+1])
285  value = (v-u[k])/(u[k+t-1]-u[k])*SplineBlend( k, t-1, u, v );
286  else
287  value = (v-u[k])/(u[k+t-1]-u[k])*SplineBlend( k, t-1, u, v )
288  +(u[k+t]-v)/(u[k+t]-u[k+1])*SplineBlend( k+1, t-1, u, v );
289  }
290  return value;
291 }
292 
293 /*
294  * The positions of the subintervals of v and breakpoints, the position
295  * on the curve are called knots. Breakpoints can be uniformly defined
296  * by setting u[j] = j, a more useful series of breakpoints are defined
297  * by the function below. This set of breakpoints localises changes to
298  * the vicinity of the control point being modified.
299  */
300 void SplineKnots( int *u, int n, int t )
301 {
302  int j;
303  for (j = 0; j <= n+t; j++) {
304  if (j < t)
305  u[j] = 0;
306  else if (j <= n)
307  u[j] = j-t+1;
308  else if (j > n)
309  u[j] = n-t+2;
310  }
311 }
312 
313 /*-------------------------------------------------------------------------
314  * Create all the points along a spline curve
315  * Control points "inp", "n" of them.
316  * Knots "knots", degree "t".
317  * Ouput curve "outp", "res" of them.
318  */
319 void SplineCurve( XYZ *inp, int n, int *knots, int t, XYZ *outp, int res )
320 {
321  int i;
322  double interval, increment;
323 
324  interval = 0;
325  increment = (n-t+2)/(double) (res-1);
326  for (i = 0; i < res-1; i++) {
327  SplinePoint( knots, n, t, interval, inp, &(outp[i]) );
328  interval += increment;
329  }
330  outp[res-1] = inp[n];
331 }
332 
333 /*
334  * Example of how to call the spline functions
335  * Basically one needs to create the control points, then compute
336  * the knot positions, then calculate points along the curve.
337  */
338 #define N 3
339 XYZ inp[N+1] = {0.0, 0.0, 0.0, 1.0, 0.0, 3.0, 2.0, 0.0, 1.0, 4.0, 0.0, 4.0};
340 #define T 3
341 int knots[N+T+1];
342 #define RESOLUTION 200
343 XYZ outp[RESOLUTION];
344 
345 int main( int argc, char **argv )
346 {
347  int i;
348 
349  SplineKnots( knots, N, T );
350  SplineCurve( inp, N, knots, T, outp, RESOLUTION );
351 
352  /* Display the curve, in this case in OOGL format for GeomView */
353  printf( "LIST\n" );
354  printf( "{ = SKEL\n" );
355  printf( "%d %d\n", RESOLUTION, RESOLUTION-1 );
356  for (i = 0; i < RESOLUTION; i++)
357  printf( "%g %g %g\n", outp[i].x, outp[i].y, outp[i].z );
358  for (i = 0; i < RESOLUTION-1; i++)
359  printf( "2 %d %d 1 1 1 1\n", i, i+1 );
360  printf( "}\n" );
361 
362  /* The axes */
363  printf( "{ = SKEL 3 2 0 0 4 0 0 0 4 0 0 2 0 1 0 0 1 1 2 1 2 0 0 1 1 }\n" );
364 
365  /* Control point polygon */
366  printf( "{ = SKEL\n" );
367  printf( "%d %d\n", N+1, N );
368  for (i = 0; i <= N; i++)
369  printf( "%g %g %g\n", inp[i].x, inp[i].y, inp[i].z );
370  for (i = 0; i < N; i++)
371  printf( "2 %d %d 0 1 0 1\n", i, i+1 );
372  printf( "}\n" );
373 }
374 #endif
375