Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / filter / sgvspln.cxx
blob8c9c09be4d2ec3e9718d7e0b76806119b702275e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <math.h>
22 #include <tools/poly.hxx>
23 #include <boost/scoped_array.hpp>
25 #include <sgvspln.hxx>
27 extern "C" {
29 /*.pn 277 */
30 /*.hlAppendix: C - programs*/
31 /*.hrConstants- and macrodefinitions*/
32 /*.fe The include file u_const.h should be stored in the directory, */
33 /*.fe where the compiler searches for include files. */
35 /*----------------------- FILE u_const.h ---------------------------*/
37 #define IEEE
39 /* IEEE - standard for representation of floating-point numbers:
41 8 byte long floating point numbers with
43 53 bit mantissa ==> mantissa range: 2^52 different numbers
44 with 0.1 <= number < 1.0,
45 1 sign-bit
46 11 bit exponent ==> exponent range: -1024...+1023
48 The first line (#define IEEE) should be deleted if the machine
49 or the compiler does not use floating-point numbers according
50 to the IEEE standard. In which case also MAXEXPON, MINEXPON (see
51 below) should be adapted.
54 #ifdef IEEE /*-------------- if IEEE norm --------------------*/
56 #define MACH_EPS 2.220446049250313e-016 /* machine precision */
57 /* IBM-AT: = 2^-52 */
58 /* MACH_EPS is the smallest positive, by the machine representable
59 number x, which fulfills the equation: 1.0 + x > 1.0 */
61 #define MAXROOT 9.48075190810918e+153
63 #else /*------------------ otherwise--------------------*/
65 double exp (double);
66 double atan (double);
67 double pow (double,double);
68 double sqrt (double);
70 double masch() /* calculate MACH_EPS machine independence */
72 double eps = 1.0, x = 2.0, y = 1.0;
73 while ( y < x )
74 { eps *= 0.5;
75 x = 1.0 + eps;
77 eps *= 2.0;
78 return eps;
81 short basis() /* calculate BASE machine independence */
83 double x = 1.0, one = 1.0, b = 1.0;
85 while ( (x + one) - x == one ) x *= 2.0;
86 while ( (x + b) == x ) b *= 2.0;
88 return (short) ((x + b) - x);
91 #define BASIS basis() /* base of number representation */
93 /* If the machine (the compiler) does not use the IEEE-representation
94 for floating-point numbers, the next 2 constants should be adapted.
97 #define MAXEXPON 1023.0 /* largest exponent */
98 #define MINEXPON -1024.0 /* smallest exponent */
100 #define MACH_EPS masch()
102 #define POSMAX pow ((double) BASIS, MAXEXPON)
103 #define MAXROOT sqrt(POSMAX)
105 #endif /*-------------- END of ifdef --------------------*/
107 /* defines for function macros: */
109 #define abs(X) ((X) >= 0 ? (X) : -(X)) /* absolute number X */
110 #define sign(X, Y) (Y < 0 ? -abs(X) : abs(X)) /* sign of Y times */
111 /* abs(X) */
113 /*-------------------- END of FILE u_const.h -----------------------*/
115 /*.HL appendix: C - programs*/
116 /*.HR Systems of equations for tridiagonal matrices*/
118 /*.FE P 3.7 tridiagonal systems of equations */
120 /*---------------------- MODULE tridiagonal -----------------------*/
122 sal_uInt16 TriDiagGS(bool rep, sal_uInt16 n, double* lower,
123 double* diag, double* upper, double* b)
124 /*************************/
125 /* Gaussian methods for */
126 /* tridiagonal matrices */
127 /*************************/
129 /*====================================================================*/
130 /* */
131 /* trdiag determines solution x of the system of linear equations */
132 /* A * x = b with tridiagonal n x n coefficient matrix A, which is */
133 /* stored in 3 vectors lower, upper and diag as per below: */
134 /* */
135 /* ( diag[0] upper[0] 0 0 . . . 0 ) */
136 /* ( lower[1] diag[1] upper[1] 0 . . . ) */
137 /* ( 0 lower[2] diag[2] upper[2] 0 . ) */
138 /* A = ( . 0 lower[3] . . . ) */
139 /* ( . . . . . 0 ) */
140 /* ( . . . . . ) */
141 /* ( . . . upper[n-2] ) */
142 /* ( 0 . . . 0 lower[n-1] diag[n-1] ) */
143 /* */
144 /*====================================================================*/
145 /* */
146 /* Usage: */
147 /* ====== */
148 /* Mainly for diagonal determinant triangular matrix, as they */
149 /* occur in Spline-interpolations. */
150 /* For diagonal dominant matrices always a left-upper row */
151 /* reduction exists; for non diagonal dominant triangular */
152 /* matrices we should pull forward the function band, as this */
153 /* works with row pivot searches, which is numerical more stable.*/
154 /* */
155 /*====================================================================*/
156 /* */
157 /* Input parameters: */
158 /* ================ */
159 /* n dimension of the matrix ( > 1 ) sal_uInt16 n */
160 /* */
161 /* lower lower antidiagonal double lower[n] */
162 /* diag main diagonal double diag[n] */
163 /* upper upper antidiagonal double upper[n] */
164 /* */
165 /* for rep = true lower, diag and upper contain the */
166 /* triangulation of the start matrix. */
167 /* */
168 /* b right side of equation double b[n] */
169 /* rep = false first call bool rep */
170 /* = true next call */
171 /* for the same matrix, */
172 /* but different b. */
173 /* */
174 /* Output parameters: */
175 /* ================= */
176 /* b solution vector of the system; double b[n] */
177 /* the original right side is overwritten */
178 /* */
179 /* lower ) contain for rep = false the decomposition of the */
180 /* diag ) matrix; the original values of the lower and */
181 /* upper ) diagonals are overwritten */
182 /* */
183 /* The determinant of the matrix is for rep = false defined by */
184 /* determinant A = diag[0] * ... * diag[n-1] */
185 /* */
186 /* Return value: */
187 /* ============= */
188 /* = 0 all ok */
189 /* = 1 n < 2 chosen */
190 /* = 2 triangular decomposition of matrix does not exist */
191 /* */
192 /*====================================================================*/
193 /* */
194 /* Functions used: */
195 /* =============== */
196 /* */
197 /* From the C library: fabs() */
198 /* */
199 /*====================================================================*/
201 /*.cp 5 */
203 sal_uInt16 i;
204 short j;
206 // double fabs(double);
208 if ( n < 2 ) return 1; /* n at least 2 */
210 /* if rep = false, */
211 /* determine the */
212 /* triangular */
213 /* decomposition of */
214 if (!rep) /* matrix and determinant*/
216 for (i = 1; i < n; i++)
217 { if ( fabs(diag[i-1]) < MACH_EPS ) /* do not decompose */
218 return 2; /* if one diag[i] = 0 */
219 lower[i] /= diag[i-1];
220 diag[i] -= lower[i] * upper[i-1];
224 if ( fabs(diag[n-1]) < MACH_EPS ) return 2;
226 for (i = 1; i < n; i++) /* forward elimination */
227 b[i] -= lower[i] * b[i-1];
229 b[n-1] /= diag[n-1]; /* reverse elimination */
230 for (j = n-2; j >= 0; j--) {
231 i=j;
232 b[i] = ( b[i] - upper[i] * b[i+1] ) / diag[i];
234 return 0;
237 /*----------------------- END OF TRIDIAGONAL ------------------------*/
239 /*.HL Appendix: C - Programs*/
240 /*.HRSystems of equations with cyclic tridiagonal matrices*/
242 /*.FE P 3.8 Systems with cyclic tridiagonal matrices */
244 /*---------------- Module cyclic tridiagonal -----------------------*/
246 sal_uInt16 ZyklTriDiagGS(bool rep, sal_uInt16 n, double* lower, double* diag,
247 double* upper, double* lowrow, double* ricol, double* b)
248 /******************************/
249 /* Systems with cyclic */
250 /* tridiagonal matrices */
251 /******************************/
253 /*====================================================================*/
254 /* */
255 /* tzdiag determines the solution x of the linear equation system */
256 /* A * x = b with cyclic tridiagonal n x n coefficient- */
257 /* matrix A, which is stored in the 5 vectors: lower, upper, diag, */
258 /* lowrow and ricol as per below: */
259 /* */
260 /* ( diag[0] upper[0] 0 0 . . 0 ricol[0] ) */
261 /* ( lower[1] diag[1] upper[1] 0 . . 0 ) */
262 /* ( 0 lower[2] diag[2] upper[2] 0 . ) */
263 /* A = ( . 0 lower[3] . . . . ) */
264 /* ( . . . . . 0 ) */
265 /* ( . . . . . ) */
266 /* ( 0 . . . upper[n-2] ) */
267 /* ( lowrow[0] 0 . . 0 lower[n-1] diag[n-1] ) */
268 /* */
269 /* Memory for lowrow[1],..,lowrow[n-3] und ricol[1],...,ricol[n-3] */
270 /* should be provided separately, as this should be available to */
271 /* store the decomposition matrix, which is overwritting */
272 /* the 5 vectors mentioned. */
273 /* */
274 /*====================================================================*/
275 /* */
276 /* Usage: */
277 /* ====== */
278 /* Predominantly for diagonal dominant cyclic tridiagonal- */
279 /* matrices as they occur in spline-interpolations. */
280 /* For diagonal dominant matices only a LU-decomposition exists. */
281 /* */
282 /*====================================================================*/
283 /* */
284 /* Input parameters: */
285 /* ================= */
286 /* n Dimension of the matrix ( > 2 ) sal_uInt16 n */
287 /* lower lower antidiagonal double lower[n] */
288 /* diag main diagonal double diag[n] */
289 /* upper upper antidiagonal double upper[n] */
290 /* b right side of the system double b[n] */
291 /* rep = FALSE first call bool rep */
292 /* = TRUE repeated call */
293 /* for equal matrix, */
294 /* but different b. */
295 /* */
296 /* Output parameters: */
297 /* ================== */
298 /* b solution vector of the system, double b[n] */
299 /* the original right side is overwritten */
300 /* */
301 /* lower ) contain for rep = false the solution of the matrix;*/
302 /* diag ) the original values of lower and diagonal will be */
303 /* upper ) overwritten */
304 /* lowrow ) double lowrow[n-2] */
305 /* ricol ) double ricol[n-2] */
306 /* */
307 /* The determinant of the matrix is for rep = false */
308 /* det A = diag[0] * ... * diag[n-1] defined . */
309 /* */
310 /* Return value: */
311 /* ============= */
312 /* = 0 all ok */
313 /* = 1 n < 3 chosen */
314 /* = 2 Decomposition matrix does not exist */
315 /* */
316 /*====================================================================*/
317 /* */
318 /* Used functions: */
319 /* =============== */
320 /* */
321 /* from the C library: fabs() */
322 /* */
323 /*====================================================================*/
325 /*.cp 5 */
327 double temp; // fabs(double);
328 sal_uInt16 i;
329 short j;
331 if ( n < 3 ) return 1;
333 if (!rep) /* If rep = false, */
334 { /* calculate decomposition */
335 lower[0] = upper[n-1] = 0.0; /* of the matrix. */
337 if ( fabs (diag[0]) < MACH_EPS ) return 2;
338 /* Do not decompose if the */
339 temp = 1.0 / diag[0]; /* value of a diagonal */
340 upper[0] *= temp; /* element is smaller then */
341 ricol[0] *= temp; /* MACH_EPS */
343 for (i = 1; i < n-2; i++)
344 { diag[i] -= lower[i] * upper[i-1];
345 if ( fabs(diag[i]) < MACH_EPS ) return 2;
346 temp = 1.0 / diag[i];
347 upper[i] *= temp;
348 ricol[i] = -lower[i] * ricol[i-1] * temp;
351 diag[n-2] -= lower[n-2] * upper[n-3];
352 if ( fabs(diag[n-2]) < MACH_EPS ) return 2;
354 for (i = 1; i < n-2; i++)
355 lowrow[i] = -lowrow[i-1] * upper[i-1];
357 lower[n-1] -= lowrow[n-3] * upper[n-3];
358 upper[n-2] = ( upper[n-2] - lower[n-2] * ricol[n-3] ) / diag[n-2];
360 for (temp = 0.0, i = 0; i < n-2; i++)
361 temp -= lowrow[i] * ricol[i];
362 diag[n-1] += temp - lower[n-1] * upper[n-2];
364 if ( fabs(diag[n-1]) < MACH_EPS ) return 2;
367 b[0] /= diag[0]; /* forward elimination */
368 for (i = 1; i < n-1; i++)
369 b[i] = ( b[i] - b[i-1] * lower[i] ) / diag[i];
371 for (temp = 0.0, i = 0; i < n-2; i++)
372 temp -= lowrow[i] * b[i];
374 b[n-1] = ( b[n-1] + temp - lower[n-1] * b[n-2] ) / diag[n-1];
376 b[n-2] -= b[n-1] * upper[n-2]; /* backward elimination */
377 for (j = n-3; j >= 0; j--) {
378 i=j;
379 b[i] -= upper[i] * b[i+1] + ricol[i] * b[n-1];
381 return 0;
384 /*------------------ END of CYCLIC TRIDIAGONAL ---------------------*/
386 } // extern "C"
388 // Calculates the coefficients of natural cubic splines with n intervals.
389 sal_uInt16 NaturalSpline(sal_uInt16 n, double* x, double* y,
390 double Marg0, double MargN,
391 sal_uInt8 MargCond,
392 double* b, double* c, double* d)
394 sal_uInt16 i;
395 boost::scoped_array<double> a;
396 boost::scoped_array<double> h;
397 sal_uInt16 error;
399 if (n<2) return 1;
400 if ( (MargCond & ~3) ) return 2;
401 a.reset(new double[n+1]);
402 h.reset(new double[n+1]);
403 for (i=0;i<n;i++) {
404 h[i]=x[i+1]-x[i];
405 if (h[i]<=0.0) return 1;
407 for (i=0;i<n-1;i++) {
408 a[i]=3.0*((y[i+2]-y[i+1])/h[i+1]-(y[i+1]-y[i])/h[i]);
409 b[i]=h[i];
410 c[i]=h[i+1];
411 d[i]=2.0*(h[i]+h[i+1]);
413 switch (MargCond) {
414 case 0: {
415 if (n==2) {
416 a[0]=a[0]/3.0;
417 d[0]=d[0]*0.5;
418 } else {
419 a[0] =a[0]*h[1]/(h[0]+h[1]);
420 a[n-2]=a[n-2]*h[n-2]/(h[n-1]+h[n-2]);
421 d[0] =d[0]-h[0];
422 d[n-2]=d[n-2]-h[n-1];
423 c[0] =c[0]-h[0];
424 b[n-2]=b[n-2]-h[n-1];
427 case 1: {
428 a[0] =a[0]-1.5*((y[1]-y[0])/h[0]-Marg0);
429 a[n-2]=a[n-2]-1.5*(MargN-(y[n]-y[n-1])/h[n-1]);
430 d[0] =d[0]-h[0]*0.5;
431 d[n-2]=d[n-2]-h[n-1]*0.5;
433 case 2: {
434 a[0] =a[0]-h[0]*Marg0*0.5;
435 a[n-2]=a[n-2]-h[n-1]*MargN*0.5;
437 case 3: {
438 a[0] =a[0]+Marg0*h[0]*h[0]*0.5;
439 a[n-2]=a[n-2]-MargN*h[n-1]*h[n-1]*0.5;
440 d[0] =d[0]+h[0];
441 d[n-2]=d[n-2]+h[n-1];
443 } // switch MargCond
444 if (n==2) {
445 c[1]=a[0]/d[0];
446 } else {
447 error=TriDiagGS(false,n-1,b,d,c,a.get());
448 if (error!=0) return error+2;
449 for (i=0;i<n-1;i++) c[i+1]=a[i];
451 switch (MargCond) {
452 case 0: {
453 if (n==2) {
454 c[2]=c[1];
455 c[0]=c[1];
456 } else {
457 c[0]=c[1]+h[0]*(c[1]-c[2])/h[1];
458 c[n]=c[n-1]+h[n-1]*(c[n-1]-c[n-2])/h[n-2];
461 case 1: {
462 c[0]=1.5*((y[1]-y[0])/h[0]-Marg0);
463 c[0]=(c[0]-c[1]*h[0]*0.5)/h[0];
464 c[n]=1.5*((y[n]-y[n-1])/h[n-1]-MargN);
465 c[n]=(c[n]-c[n-1]*h[n-1]*0.5)/h[n-1];
467 case 2: {
468 c[0]=Marg0*0.5;
469 c[n]=MargN*0.5;
471 case 3: {
472 c[0]=c[1]-Marg0*h[0]*0.5;
473 c[n]=c[n-1]+MargN*h[n-1]*0.5;
475 } // switch MargCond
476 for (i=0;i<n;i++) {
477 b[i]=(y[i+1]-y[i])/h[i]-h[i]*(c[i+1]+2.0*c[i])/3.0;
478 d[i]=(c[i+1]-c[i])/(3.0*h[i]);
480 return 0;
483 // calculates the coefficients of periodical cubic splines with n intervals.
484 sal_uInt16 PeriodicSpline(sal_uInt16 n, double* x, double* y,
485 double* b, double* c, double* d)
486 { // array dimensions should range from [0..n]!
487 sal_uInt16 Error;
488 sal_uInt16 i,im1,nm1; //integer
489 double hr,hl;
490 boost::scoped_array<double> a;
491 boost::scoped_array<double> lowrow;
492 boost::scoped_array<double> ricol;
494 if (n<2) return 4;
495 nm1=n-1;
496 for (i=0;i<=nm1;i++) if (x[i+1]<=x[i]) return 2; // should be strictly monotonically decreasing!
497 if (y[n]!=y[0]) return 3; // begin and end should be equal!
499 a.reset(new double[n+1]);
500 lowrow.reset(new double[n+1]);
501 ricol.reset(new double[n+1]);
503 if (n==2) {
504 c[1]=3.0*((y[2]-y[1])/(x[2]-x[1]));
505 c[1]=c[1]-3.0*((y[i]-y[0])/(x[1]-x[0]));
506 c[1]=c[1]/(x[2]-x[0]);
507 c[2]=-c[1];
508 } else {
509 for (i=1;i<=nm1;i++) {
510 im1=i-1;
511 hl=x[i]-x[im1];
512 hr=x[i+1]-x[i];
513 b[im1]=hl;
514 d[im1]=2.0*(hl+hr);
515 c[im1]=hr;
516 a[im1]=3.0*((y[i+1]-y[i])/hr-(y[i]-y[im1])/hl);
518 hl=x[n]-x[nm1];
519 hr=x[1]-x[0];
520 b[nm1]=hl;
521 d[nm1]=2.0*(hl+hr);
522 lowrow[0]=hr;
523 ricol[0]=hr;
524 a[nm1]=3.0*((y[1]-y[0])/hr-(y[n]-y[nm1])/hl);
525 Error=ZyklTriDiagGS(false,n,b,d,c,lowrow.get(),ricol.get(),a.get());
526 if ( Error != 0 )
528 return Error+4;
530 for (i=0;i<=nm1;i++) c[i+1]=a[i];
532 c[0]=c[n];
533 for (i=0;i<=nm1;i++) {
534 hl=x[i+1]-x[i];
535 b[i]=(y[i+1]-y[i])/hl;
536 b[i]=b[i]-hl*(c[i+1]+2.0*c[i])/3.0;
537 d[i]=(c[i+1]-c[i])/hl/3.0;
539 return 0;
542 // calculate the coefficients of parametric natural of periodical cubic splines
543 // with n intervals
544 sal_uInt16 ParaSpline(sal_uInt16 n, double* x, double* y, sal_uInt8 MargCond,
545 double Marg01, double Marg02,
546 double MargN1, double MargN2,
547 bool CondT, double* T,
548 double* bx, double* cx, double* dx,
549 double* by, double* cy, double* dy)
551 sal_uInt16 Error;
552 sal_uInt16 i;
553 double deltX,deltY,delt,
554 alphX = 0,alphY = 0,
555 betX = 0,betY = 0;
557 if (n<2) return 1;
558 if ((MargCond & ~3) && (MargCond != 4)) return 2; // invalid boundary condition
559 if (!CondT) {
560 T[0]=0.0;
561 for (i=0;i<n;i++) {
562 deltX=x[i+1]-x[i]; deltY=y[i+1]-y[i];
563 delt =deltX*deltX+deltY*deltY;
564 if (delt<=0.0) return 3; // two identical adjacent points!
565 T[i+1]=T[i]+sqrt(delt);
568 switch (MargCond) {
569 case 0: break;
570 case 1: case 2: {
571 alphX=Marg01; betX=MargN1;
572 alphY=Marg02; betY=MargN2;
573 } break;
574 case 3: {
575 if (x[n]!=x[0]) return 3;
576 if (y[n]!=y[0]) return 4;
577 } break;
578 case 4: {
579 if (abs(Marg01)>=MAXROOT) {
580 alphX=0.0;
581 alphY=sign(1.0,y[1]-y[0]);
582 } else {
583 alphX=sign(sqrt(1.0/(1.0+Marg01*Marg01)),x[1]-x[0]);
584 alphY=alphX*Marg01;
586 if (abs(MargN1)>=MAXROOT) {
587 betX=0.0;
588 betY=sign(1.0,y[n]-y[n-1]);
589 } else {
590 betX=sign(sqrt(1.0/(1.0+MargN1*MargN1)),x[n]-x[n-1]);
591 betY=betX*MargN1;
594 } // switch MargCond
595 if (MargCond==3) {
596 Error=PeriodicSpline(n,T,x,bx,cx,dx);
597 if (Error!=0) return Error+4;
598 Error=PeriodicSpline(n,T,y,by,cy,dy);
599 if (Error!=0) return Error+10;
600 } else {
601 Error=NaturalSpline(n,T,x,alphX,betX,MargCond,bx,cx,dx);
602 if (Error!=0) return Error+4;
603 Error=NaturalSpline(n,T,y,alphY,betY,MargCond,by,cy,dy);
604 if (Error!=0) return Error+9;
606 return 0;
609 bool CalcSpline(Polygon& rPoly, bool Periodic, sal_uInt16& n,
610 double*& ax, double*& ay, double*& bx, double*& by,
611 double*& cx, double*& cy, double*& dx, double*& dy, double*& T)
613 sal_uInt8 Marg;
614 double Marg01;
615 double MargN1,MargN2;
616 sal_uInt16 i;
617 Point P0(-32768,-32768);
618 Point Pt;
620 n=rPoly.GetSize();
621 ax=new double[rPoly.GetSize()+2];
622 ay=new double[rPoly.GetSize()+2];
624 n=0;
625 for (i=0;i<rPoly.GetSize();i++) {
626 Pt=rPoly.GetPoint(i);
627 if (i==0 || Pt!=P0) {
628 ax[n]=Pt.X();
629 ay[n]=Pt.Y();
630 n++;
631 P0=Pt;
635 if (Periodic) {
636 Marg=3;
637 ax[n]=ax[0];
638 ay[n]=ay[0];
639 n++;
640 } else {
641 Marg=2;
644 bx=new double[n+1];
645 by=new double[n+1];
646 cx=new double[n+1];
647 cy=new double[n+1];
648 dx=new double[n+1];
649 dy=new double[n+1];
650 T =new double[n+1];
652 Marg01=0.0;
653 MargN1=0.0;
654 MargN2=0.0;
655 if (n>0) n--; // correct n (number of partial polynoms)
657 bool bRet = false;
658 if ( ( Marg == 3 && n >= 3 ) || ( Marg == 2 && n >= 2 ) )
660 bRet = ParaSpline(n,ax,ay,Marg,Marg01,Marg01,MargN1,MargN2,false,T,bx,cx,dx,by,cy,dy) == 0;
662 if ( !bRet )
664 delete[] ax;
665 delete[] ay;
666 delete[] bx;
667 delete[] by;
668 delete[] cx;
669 delete[] cy;
670 delete[] dx;
671 delete[] dy;
672 delete[] T;
673 n=0;
675 return bRet;
678 bool Spline2Poly(Polygon& rSpln, bool Periodic, Polygon& rPoly)
680 short MinKoord=-32000; // to prevent
681 short MaxKoord=32000; // overflows
683 double* ax; // coefficients of the polynoms
684 double* ay;
685 double* bx;
686 double* by;
687 double* cx;
688 double* cy;
689 double* dx;
690 double* dy;
691 double* tv;
693 double Step; // stepsize for t
694 double dt1,dt2,dt3; // delta t, y, ^3
695 sal_uInt16 n; // number of partial polynoms to draw
696 sal_uInt16 i; // actual partial polynom
697 bool bOk; // all still ok?
698 sal_uInt16 PolyMax=16380; // max number of polygon points
700 bOk=CalcSpline(rSpln,Periodic,n,ax,ay,bx,by,cx,cy,dx,dy,tv);
701 if (bOk) {
702 Step =10;
704 rPoly.SetSize(1);
705 rPoly.SetPoint(Point(short(ax[0]),short(ay[0])),0); // first point
706 i=0;
707 while (i<n) { // draw n partial polynoms
708 double t=tv[i]+Step;
709 bool bEnd=false; // partial polynom ended?
710 while (!bEnd) { // extrapolate one partial polynom
711 bEnd=t>=tv[i+1];
712 if (bEnd) t=tv[i+1];
713 dt1=t-tv[i]; dt2=dt1*dt1; dt3=dt2*dt1;
714 long x=long(ax[i]+bx[i]*dt1+cx[i]*dt2+dx[i]*dt3);
715 long y=long(ay[i]+by[i]*dt1+cy[i]*dt2+dy[i]*dt3);
716 if (x<MinKoord) x=MinKoord; if (x>MaxKoord) x=MaxKoord;
717 if (y<MinKoord) y=MinKoord; if (y>MaxKoord) y=MaxKoord;
718 if (rPoly.GetSize()<PolyMax) {
719 rPoly.SetSize(rPoly.GetSize()+1);
720 rPoly.SetPoint(Point(short(x),short(y)),rPoly.GetSize()-1);
721 } else {
722 bOk=false; // error: polygon becomes to large
724 t=t+Step;
725 } // end of partial polynom
726 i++; // next partial polynom
728 delete[] ax;
729 delete[] ay;
730 delete[] bx;
731 delete[] by;
732 delete[] cx;
733 delete[] cy;
734 delete[] dx;
735 delete[] dy;
736 delete[] tv;
737 return bOk;
738 } // end of if (bOk)
739 rPoly.SetSize(0);
740 return false;
743 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */