1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sgvspln.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
37 #include <tools/poly.hxx>
39 #if defined( WIN ) && defined( MSC )
40 #pragma code_seg( "SVTOOLS_FILTER2", "SVTOOLS_CODE" )
41 #pragma optimize( "", off )
44 #if defined( PM2 ) && defined( __BORLANDC__ )
51 /*.hlAnhang: C - Programme*/
52 /*.hrKonstanten- und Macro-Definitionen*/
53 /*.fe Die Include-Datei u_const.h ist in das Verzeichnis zu stellen, */
54 /*.fe wo der Compiler nach Include-Dateien sucht. */
57 /*----------------------- FILE u_const.h ---------------------------*/
61 /* IEEE - Norm fuer die Darstellung von Gleitkommazahlen:
63 8 Byte lange Gleitkommazahlen, mit
65 53 Bit Mantisse ==> Mantissenbereich: 2 hoch 52 versch. Zahlen
66 mit 0.1 <= Zahl < 1.0,
68 11 Bit Exponent ==> Exponentenbereich: -1024...+1023
70 Die 1. Zeile ( #define IEEE ) ist zu loeschen, falls die Maschine
71 bzw. der Compiler keine Gleitpunktzahlen gemaess der IEEE-Norm
72 benutzt. Zusaetzlich muessen die Zahlen MAXEXPON, MINEXPON
73 (s.u.) angepasst werden.
76 #ifdef IEEE /*----------- Falls IEEE Norm --------------------*/
78 #define MACH_EPS 2.220446049250313e-016 /* Maschinengenauigkeit */
79 /* IBM-AT: = 2 hoch -52 */
80 /* MACH_EPS ist die kleinste positive, auf der Maschine darstellbare
81 Zahl x, die der Bedingung genuegt: 1.0 + x > 1.0 */
83 #define EPSQUAD 4.930380657631324e-032
84 #define EPSROOT 1.490116119384766e-008
86 #define POSMAX 8.98846567431158e+307 /* groesste positive Zahl */
87 #define POSMIN 5.56268464626800e-309 /* kleinste positive Zahl */
88 #define MAXROOT 9.48075190810918e+153
90 #define BASIS 2 /* Basis der Zahlendarst. */
92 #define PI 3.141592653589793e+000
94 #define EXP_1 2.718281828459045e+000
96 #else /*------------------ sonst -----------------------*/
100 double pow (double,double);
101 double sqrt (double);
103 double masch() /* MACH_EPS maschinenunabhaengig bestimmen */
105 double eps
= 1.0, x
= 2.0, y
= 1.0;
110 eps
*= 2.0; return (eps
);
113 short basis() /* BASIS maschinenunabhaengig bestimmen */
115 double x
= 1.0, one
= 1.0, b
= 1.0;
117 while ( (x
+ one
) - x
== one
) x
*= 2.0;
118 while ( (x
+ b
) == x
) b
*= 2.0;
120 return ( (short) ((x
+ b
) - x
) );
123 #define BASIS basis() /* Basis der Zahlendarst. */
125 /* Falls die Maschine (der Compiler) keine IEEE-Darstellung fuer
126 Gleitkommazahlen nutzt, muessen die folgenden 2 Konstanten an-
130 #define MAXEXPON 1023.0 /* groesster Exponent */
131 #define MINEXPON -1024.0 /* kleinster Exponent */
134 #define MACH_EPS masch()
135 #define EPSQUAD MACH_EPS * MACH_EPS
136 #define EPSROOT sqrt(MACH_EPS)
138 #define POSMAX pow ((double) BASIS, MAXEXPON)
139 #define POSMIN pow ((double) BASIS, MINEXPON)
140 #define MAXROOT sqrt(POSMAX)
142 #define PI 4.0 * atan (1.0)
143 #define EXP_1 exp(1.0)
145 #endif /*-------------- ENDE ifdef ----------------------*/
148 #define NEGMAX -POSMIN /* groesste negative Zahl */
149 #define NEGMIN -POSMAX /* kleinste negative Zahl */
155 /* Definition von Funktionsmakros:
158 #define abs(X) ((X) >= 0 ? (X) : -(X)) /* Absolutbetrag von X */
159 #define sign(X, Y) (Y < 0 ? -abs(X) : abs(X)) /* Vorzeichen von */
161 #define sqr(X) ((X) * (X)) /* Quadrat von X */
163 /*------------------- ENDE FILE u_const.h --------------------------*/
173 /*.HL Anhang: C - Programme*/
174 /*.HRGleichungssysteme fuer Tridiagonalmatrizen*/
176 /*.FE P 3.7 TRIDIAGONALE GLEICHUNGSSYSTEME*/
179 /*---------------------- MODUL TRIDIAGONAL ------------------------*/
181 USHORT
TriDiagGS(BOOL rep
, USHORT n
, double* lower
,
182 double* diag
, double* upper
, double* b
)
183 /************************/
184 /* GAUSS-Verfahren fuer */
185 /* Tridiagonalmatrizen */
186 /************************/
188 /*====================================================================*/
190 /* trdiag bestimmt die Loesung x des linearen Gleichungssystems */
191 /* A * x = b mit tridiagonaler n x n Koeffizientenmatrix A, die in */
192 /* den 3 Vektoren lower, upper und diag wie folgt abgespeichert ist: */
194 /* ( diag[0] upper[0] 0 0 . . . 0 ) */
195 /* ( lower[1] diag[1] upper[1] 0 . . . ) */
196 /* ( 0 lower[2] diag[2] upper[2] 0 . ) */
197 /* A = ( . 0 lower[3] . . . ) */
198 /* ( . . . . . 0 ) */
200 /* ( . . . upper[n-2] ) */
201 /* ( 0 . . . 0 lower[n-1] diag[n-1] ) */
203 /*====================================================================*/
207 /* Vorwiegend fuer diagonaldominante Tridiagonalmatrizen, wie */
208 /* sie bei der Spline-Interpolation auftreten. */
209 /* Fuer diagonaldominante Matrizen existiert immer eine LU- */
210 /* Zerlegung; fuer nicht diagonaldominante Tridiagonalmatrizen */
211 /* sollte die Funktion band vorgezogen werden, da diese mit */
212 /* Spaltenpivotsuche arbeitet und daher numerisch stabiler ist. */
214 /*====================================================================*/
216 /* Eingabeparameter: */
217 /* ================ */
218 /* n Dimension der Matrix ( > 1 ) USHORT n */
220 /* lower untere Nebendiagonale double lower[n] */
221 /* diag Hauptdiagonale double diag[n] */
222 /* upper obere Nebendiagonale double upper[n] */
224 /* bei rep != 0 enthalten lower, diag und upper die */
225 /* Dreieckzerlegung der Ausgangsmatrix. */
227 /* b rechte Seite des Systems double b[n] */
228 /* rep = 0 erstmaliger Aufruf BOOL rep */
229 /* !=0 wiederholter Aufruf */
230 /* fuer gleiche Matrix, */
231 /* aber verschiedenes b. */
233 /* Ausgabeparameter: */
234 /* ================ */
235 /* b Loesungsvektor des Systems; double b[n] */
236 /* die urspruengliche rechte Seite wird ueberspeichert */
238 /* lower ) enthalten bei rep = 0 die Zerlegung der Matrix; */
239 /* diag ) die urspruenglichen Werte von lower u. diag werden */
240 /* upper ) ueberschrieben */
242 /* Die Determinante der Matrix ist bei rep = 0 durch */
243 /* det A = diag[0] * ... * diag[n-1] bestimmt. */
248 /* = 1 n < 2 gewaehlt */
249 /* = 2 Die Dreieckzerlegung der Matrix existiert nicht */
251 /*====================================================================*/
253 /* Benutzte Funktionen: */
254 /* =================== */
256 /* Aus der C Bibliothek: fabs() */
258 /*====================================================================*/
265 // double fabs(double);
267 if ( n
< 2 ) return(1); /* n mindestens 2 */
269 /* Wenn rep = 0 ist, */
270 /* Dreieckzerlegung der */
271 if (rep
== 0) /* Matrix u. det be- */
273 for (i
= 1; i
< n
; i
++)
274 { if ( fabs(diag
[i
-1]) < MACH_EPS
) /* Wenn ein diag[i] = 0 */
275 return(2); /* ist, ex. keine Zerle- */
276 lower
[i
] /= diag
[i
-1]; /* gung. */
277 diag
[i
] -= lower
[i
] * upper
[i
-1];
281 if ( fabs(diag
[n
-1]) < MACH_EPS
) return(2);
283 for (i
= 1; i
< n
; i
++) /* Vorwaertselimination */
284 b
[i
] -= lower
[i
] * b
[i
-1];
286 b
[n
-1] /= diag
[n
-1]; /* Rueckwaertselimination */
287 for (j
= n
-2; j
>= 0; j
--) {
289 b
[i
] = ( b
[i
] - upper
[i
] * b
[i
+1] ) / diag
[i
];
294 /*----------------------- ENDE TRIDIAGONAL -------------------------*/
304 /*.HL Anhang: C - Programme*/
305 /*.HRGleichungssysteme mit zyklisch tridiagonalen Matrizen*/
307 /*.FE P 3.8 SYSTEME MIT ZYKLISCHEN TRIDIAGONALMATRIZEN */
310 /*---------------- MODUL ZYKLISCH TRIDIAGONAL ----------------------*/
313 USHORT
ZyklTriDiagGS(BOOL rep
, USHORT n
, double* lower
, double* diag
,
314 double* upper
, double* lowrow
, double* ricol
, double* b
)
315 /******************************/
316 /* Systeme mit zyklisch tri- */
317 /* diagonalen Matrizen */
318 /******************************/
320 /*====================================================================*/
322 /* tzdiag bestimmt die Loesung x des linearen Gleichungssystems */
323 /* A * x = b mit zyklisch tridiagonaler n x n Koeffizienten- */
324 /* matrix A, die in den 5 Vektoren lower, upper, diag, lowrow und */
325 /* ricol wie folgt abgespeichert ist: */
327 /* ( diag[0] upper[0] 0 0 . . 0 ricol[0] ) */
328 /* ( lower[1] diag[1] upper[1] 0 . . 0 ) */
329 /* ( 0 lower[2] diag[2] upper[2] 0 . ) */
330 /* A = ( . 0 lower[3] . . . . ) */
331 /* ( . . . . . 0 ) */
333 /* ( 0 . . . upper[n-2] ) */
334 /* ( lowrow[0] 0 . . 0 lower[n-1] diag[n-1] ) */
336 /* Speicherplatz fuer lowrow[1],..,lowrow[n-3] und ricol[1],..., */
337 /* ricol[n-3] muss zusaetzlich bereitgestellt werden, da dieser */
338 /* fuer die Aufnahme der Zerlegungsmatrix verfuegbar sein muss, die */
339 /* auf die 5 genannten Vektoren ueberspeichert wird. */
341 /*====================================================================*/
345 /* Vorwiegend fuer diagonaldominante zyklische Tridiagonalmatri- */
346 /* zen wie sie bei der Spline-Interpolation auftreten. */
347 /* Fuer diagonaldominante Matrizen existiert immer eine LU- */
350 /*====================================================================*/
352 /* Eingabeparameter: */
353 /* ================ */
354 /* n Dimension der Matrix ( > 2 ) USHORT n */
355 /* lower untere Nebendiagonale double lower[n] */
356 /* diag Hauptdiagonale double diag[n] */
357 /* upper obere Nebendiagonale double upper[n] */
358 /* b rechte Seite des Systems double b[n] */
359 /* rep = 0 erstmaliger Aufruf BOOL rep */
360 /* !=0 wiederholter Aufruf */
361 /* fuer gleiche Matrix, */
362 /* aber verschiedenes b. */
364 /* Ausgabeparameter: */
365 /* ================ */
366 /* b Loesungsvektor des Systems, double b[n] */
367 /* die urspruengliche rechte Seite wird ueberspeichert */
369 /* lower ) enthalten bei rep = 0 die Zerlegung der Matrix; */
370 /* diag ) die urspruenglichen Werte von lower u. diag werden */
371 /* upper ) ueberschrieben */
372 /* lowrow ) double lowrow[n-2] */
373 /* ricol ) double ricol[n-2] */
375 /* Die Determinante der Matrix ist bei rep = 0 durch */
376 /* det A = diag[0] * ... * diag[n-1] bestimmt. */
381 /* = 1 n < 3 gewaehlt */
382 /* = 2 Die Zerlegungsmatrix existiert nicht */
384 /*====================================================================*/
386 /* Benutzte Funktionen: */
387 /* =================== */
389 /* Aus der C Bibliothek: fabs() */
391 /*====================================================================*/
395 double temp
; // fabs(double);
399 if ( n
< 3 ) return(1);
401 if (rep
== 0) /* Wenn rep = 0 ist, */
402 { /* Zerlegung der */
403 lower
[0] = upper
[n
-1] = 0.0; /* Matrix berechnen. */
405 if ( fabs (diag
[0]) < MACH_EPS
) return(2);
406 /* Ist ein Diagonalelement */
407 temp
= 1.0 / diag
[0]; /* betragsmaessig kleiner */
408 upper
[0] *= temp
; /* MACH_EPS, so ex. keine */
409 ricol
[0] *= temp
; /* Zerlegung. */
411 for (i
= 1; i
< n
-2; i
++)
412 { diag
[i
] -= lower
[i
] * upper
[i
-1];
413 if ( fabs(diag
[i
]) < MACH_EPS
) return(2);
414 temp
= 1.0 / diag
[i
];
416 ricol
[i
] = -lower
[i
] * ricol
[i
-1] * temp
;
419 diag
[n
-2] -= lower
[n
-2] * upper
[n
-3];
420 if ( fabs(diag
[n
-2]) < MACH_EPS
) return(2);
422 for (i
= 1; i
< n
-2; i
++)
423 lowrow
[i
] = -lowrow
[i
-1] * upper
[i
-1];
425 lower
[n
-1] -= lowrow
[n
-3] * upper
[n
-3];
426 upper
[n
-2] = ( upper
[n
-2] - lower
[n
-2] * ricol
[n
-3] ) / diag
[n
-2];
428 for (temp
= 0.0, i
= 0; i
< n
-2; i
++)
429 temp
-= lowrow
[i
] * ricol
[i
];
430 diag
[n
-1] += temp
- lower
[n
-1] * upper
[n
-2];
432 if ( fabs(diag
[n
-1]) < MACH_EPS
) return(2);
433 } /* end if ( rep == 0 ) */
435 b
[0] /= diag
[0]; /* Vorwaertselemination */
436 for (i
= 1; i
< n
-1; i
++)
437 b
[i
] = ( b
[i
] - b
[i
-1] * lower
[i
] ) / diag
[i
];
439 for (temp
= 0.0, i
= 0; i
< n
-2; i
++)
440 temp
-= lowrow
[i
] * b
[i
];
442 b
[n
-1] = ( b
[n
-1] + temp
- lower
[n
-1] * b
[n
-2] ) / diag
[n
-1];
444 b
[n
-2] -= b
[n
-1] * upper
[n
-2]; /* Rueckwaertselimination */
445 for (j
= n
-3; j
>= 0; j
--) {
447 b
[i
] -= upper
[i
] * b
[i
+1] + ricol
[i
] * b
[n
-1];
452 /*------------------ ENDE ZYKLISCH TRIDIAGONAL ---------------------*/
458 /*************************************************************************
462 |* Beschreibung Berechnet die Koeffizienten eines natuerlichen
463 |* kubischen Polynomsplines mit n Stuetzstellen.
464 |* Ersterstellung JOE 17-08.93
465 |* Letzte Aenderung JOE 17-08.93
467 *************************************************************************/
469 USHORT
NaturalSpline(USHORT n
, double* x
, double* y
,
470 double Marg0
, double MargN
,
472 double* b
, double* c
, double* d
)
480 if ( (MargCond
& ~3) ) return 2;
485 if (h
[i
]<=0.0) { delete[] a
; delete[] h
; return 1; }
487 for (i
=0;i
<n
-1;i
++) {
488 a
[i
]=3.0*((y
[i
+2]-y
[i
+1])/h
[i
+1]-(y
[i
+1]-y
[i
])/h
[i
]);
491 d
[i
]=2.0*(h
[i
]+h
[i
+1]);
499 a
[0] =a
[0]*h
[1]/(h
[0]+h
[1]);
500 a
[n
-2]=a
[n
-2]*h
[n
-2]/(h
[n
-1]+h
[n
-2]);
502 d
[n
-2]=d
[n
-2]-h
[n
-1];
504 b
[n
-2]=b
[n
-2]-h
[n
-1];
508 a
[0] =a
[0]-1.5*((y
[1]-y
[0])/h
[0]-Marg0
);
509 a
[n
-2]=a
[n
-2]-1.5*(MargN
-(y
[n
]-y
[n
-1])/h
[n
-1]);
511 d
[n
-2]=d
[n
-2]-h
[n
-1]*0.5;
514 a
[0] =a
[0]-h
[0]*Marg0
*0.5;
515 a
[n
-2]=a
[n
-2]-h
[n
-1]*MargN
*0.5;
518 a
[0] =a
[0]+Marg0
*h
[0]*h
[0]*0.5;
519 a
[n
-2]=a
[n
-2]-MargN
*h
[n
-1]*h
[n
-1]*0.5;
521 d
[n
-2]=d
[n
-2]+h
[n
-1];
527 error
=TriDiagGS(FALSE
,n
-1,b
,d
,c
,a
);
528 if (error
!=0) { delete[] a
; delete[] h
; return error
+2; }
529 for (i
=0;i
<n
-1;i
++) c
[i
+1]=a
[i
];
537 c
[0]=c
[1]+h
[0]*(c
[1]-c
[2])/h
[1];
538 c
[n
]=c
[n
-1]+h
[n
-1]*(c
[n
-1]-c
[n
-2])/h
[n
-2];
542 c
[0]=1.5*((y
[1]-y
[0])/h
[0]-Marg0
);
543 c
[0]=(c
[0]-c
[1]*h
[0]*0.5)/h
[0];
544 c
[n
]=1.5*((y
[n
]-y
[n
-1])/h
[n
-1]-MargN
);
545 c
[n
]=(c
[n
]-c
[n
-1]*h
[n
-1]*0.5)/h
[n
-1];
552 c
[0]=c
[1]-Marg0
*h
[0]*0.5;
553 c
[n
]=c
[n
-1]+MargN
*h
[n
-1]*0.5;
557 b
[i
]=(y
[i
+1]-y
[i
])/h
[i
]-h
[i
]*(c
[i
+1]+2.0*c
[i
])/3.0;
558 d
[i
]=(c
[i
+1]-c
[i
])/(3.0*h
[i
]);
566 /*************************************************************************
570 |* Beschreibung Berechnet die Koeffizienten eines periodischen
571 |* kubischen Polynomsplines mit n Stuetzstellen.
572 |* Ersterstellung JOE 17-08.93
573 |* Letzte Aenderung JOE 17-08.93
575 *************************************************************************/
578 USHORT
PeriodicSpline(USHORT n
, double* x
, double* y
,
579 double* b
, double* c
, double* d
)
580 { // Arrays muessen von [0..n] dimensioniert sein!
582 USHORT i
,im1
,nm1
; //integer
590 for (i
=0;i
<=nm1
;i
++) if (x
[i
+1]<=x
[i
]) return 2; // muss streng nonoton fallend sein!
591 if (y
[n
]!=y
[0]) return 3; // Anfang muss gleich Ende sein!
594 lowrow
=new double[n
+1];
595 ricol
=new double[n
+1];
598 c
[1]=3.0*((y
[2]-y
[1])/(x
[2]-x
[1]));
599 c
[1]=c
[1]-3.0*((y
[i
]-y
[0])/(x
[1]-x
[0]));
600 c
[1]=c
[1]/(x
[2]-x
[0]);
603 for (i
=1;i
<=nm1
;i
++) {
610 a
[im1
]=3.0*((y
[i
+1]-y
[i
])/hr
-(y
[i
]-y
[im1
])/hl
);
618 a
[nm1
]=3.0*((y
[1]-y
[0])/hr
-(y
[n
]-y
[nm1
])/hl
);
619 Error
=ZyklTriDiagGS(FALSE
,n
,b
,d
,c
,lowrow
,ricol
,a
);
627 for (i
=0;i
<=nm1
;i
++) c
[i
+1]=a
[i
];
630 for (i
=0;i
<=nm1
;i
++) {
632 b
[i
]=(y
[i
+1]-y
[i
])/hl
;
633 b
[i
]=b
[i
]-hl
*(c
[i
+1]+2.0*c
[i
])/3.0;
634 d
[i
]=(c
[i
+1]-c
[i
])/hl
/3.0;
644 /*************************************************************************
648 |* Beschreibung Berechnet die Koeffizienten eines parametrischen
649 |* natuerlichen oder periodischen kubischen
650 |* Polynomsplines mit n Stuetzstellen.
651 |* Ersterstellung JOE 17-08.93
652 |* Letzte Aenderung JOE 17-08.93
654 *************************************************************************/
656 USHORT
ParaSpline(USHORT n
, double* x
, double* y
, BYTE MargCond
,
657 double Marg01
, double Marg02
,
658 double MargN1
, double MargN2
,
659 BOOL CondT
, double* T
,
660 double* bx
, double* cx
, double* dx
,
661 double* by
, double* cy
, double* dy
)
665 double deltX
,deltY
,delt
,
670 if ((MargCond
& ~3) && (MargCond
!= 4)) return 2; // ungueltige Randbedingung
674 deltX
=x
[i
+1]-x
[i
]; deltY
=y
[i
+1]-y
[i
];
675 delt
=deltX
*deltX
+deltY
*deltY
;
676 if (delt
<=0.0) return 3; // zwei identische Punkte nacheinander!
677 T
[i
+1]=T
[i
]+sqrt(delt
);
681 case 0: Marg
=0; break;
684 alphX
=Marg01
; betX
=MargN1
;
685 alphY
=Marg02
; betY
=MargN2
;
688 if (x
[n
]!=x
[0]) return 3;
689 if (y
[n
]!=y
[0]) return 4;
693 if (abs(Marg01
)>=MAXROOT
) {
695 alphY
=sign(1.0,y
[1]-y
[0]);
697 alphX
=sign(sqrt(1.0/(1.0+Marg01
*Marg01
)),x
[1]-x
[0]);
700 if (abs(MargN1
)>=MAXROOT
) {
702 betY
=sign(1.0,y
[n
]-y
[n
-1]);
704 betX
=sign(sqrt(1.0/(1.0+MargN1
*MargN1
)),x
[n
]-x
[n
-1]);
710 Error
=PeriodicSpline(n
,T
,x
,bx
,cx
,dx
);
711 if (Error
!=0) return(Error
+4);
712 Error
=PeriodicSpline(n
,T
,y
,by
,cy
,dy
);
713 if (Error
!=0) return(Error
+10);
715 Error
=NaturalSpline(n
,T
,x
,alphX
,betX
,MargCond
,bx
,cx
,dx
);
716 if (Error
!=0) return(Error
+4);
717 Error
=NaturalSpline(n
,T
,y
,alphY
,betY
,MargCond
,by
,cy
,dy
);
718 if (Error
!=0) return(Error
+9);
725 /*************************************************************************
729 |* Beschreibung Berechnet die Koeffizienten eines parametrischen
730 |* natuerlichen oder periodischen kubischen
731 |* Polynomsplines. Die Eckpunkte des uebergebenen
732 |* Polygons werden als Stuetzstellen angenommen.
733 |* n liefert die Anzahl der Teilpolynome.
734 |* Ist die Berechnung fehlerfrei verlaufen, so
735 |* liefert die Funktion TRUE. Nur in diesem Fall
736 |* ist Speicher fuer die Koeffizientenarrays
737 |* allokiert, der dann spaeter vom Aufrufer mittels
738 |* delete freizugeben ist.
739 |* Ersterstellung JOE 17-08.93
740 |* Letzte Aenderung JOE 17-08.93
742 *************************************************************************/
744 BOOL
CalcSpline(Polygon
& rPoly
, BOOL Periodic
, USHORT
& n
,
745 double*& ax
, double*& ay
, double*& bx
, double*& by
,
746 double*& cx
, double*& cy
, double*& dx
, double*& dy
, double*& T
)
749 double Marg01
,Marg02
;
750 double MargN1
,MargN2
;
752 Point
P0(-32768,-32768);
756 ax
=new double[rPoly
.GetSize()+2];
757 ay
=new double[rPoly
.GetSize()+2];
760 for (i
=0;i
<rPoly
.GetSize();i
++) {
761 Pt
=rPoly
.GetPoint(i
);
762 if (i
==0 || Pt
!=P0
) {
791 if (n
>0) n
--; // n Korregieren (Anzahl der Teilpolynome)
794 if ( ( Marg
== 3 && n
>= 3 ) || ( Marg
== 2 && n
>= 2 ) )
796 bRet
= ParaSpline(n
,ax
,ay
,Marg
,Marg01
,Marg01
,MargN1
,MargN2
,FALSE
,T
,bx
,cx
,dx
,by
,cy
,dy
) == 0;
815 /*************************************************************************
819 |* Beschreibung Konvertiert einen parametrichen kubischen
820 |* Polynomspline Spline (natuerlich oder periodisch)
821 |* in ein angenaehertes Polygon.
822 |* Die Funktion liefert FALSE, wenn ein Fehler bei
823 |* der Koeffizientenberechnung aufgetreten ist oder
824 |* das Polygon zu gross wird (>PolyMax=16380). Im 1.
825 |* Fall hat das Polygon 0, im 2. Fall PolyMax Punkte.
826 |* Um Koordinatenueberlaeufe zu vermeiden werden diese
827 |* auf +/-32000 begrenzt.
828 |* Ersterstellung JOE 23.06.93
829 |* Letzte Aenderung JOE 23.06.93
831 *************************************************************************/
832 BOOL
Spline2Poly(Polygon
& rSpln
, BOOL Periodic
, Polygon
& rPoly
)
834 short MinKoord
=-32000; // zur Vermeidung
835 short MaxKoord
=32000; // von Ueberlaeufen
837 double* ax
; // Koeffizienten der Polynome
847 double Step
; // Schrittweite fuer t
848 double dt1
,dt2
,dt3
; // Delta t, y, ^3
850 BOOL bEnde
; // Teilpolynom zu Ende?
851 USHORT n
; // Anzahl der zu zeichnenden Teilpolynome
852 USHORT i
; // aktuelles Teilpolynom
853 BOOL bOk
; // noch alles ok?
854 USHORT PolyMax
=16380;// Maximale Anzahl von Polygonpunkten
857 bOk
=CalcSpline(rSpln
,Periodic
,n
,ax
,ay
,bx
,by
,cx
,cy
,dx
,dy
,tv
);
862 rPoly
.SetPoint(Point(short(ax
[0]),short(ay
[0])),0); // erster Punkt
864 while (i
<n
) { // n Teilpolynome malen
867 while (!bEnde
) { // ein Teilpolynom interpolieren
869 if (bEnde
) t
=tv
[i
+1];
870 dt1
=t
-tv
[i
]; dt2
=dt1
*dt1
; dt3
=dt2
*dt1
;
871 x
=long(ax
[i
]+bx
[i
]*dt1
+cx
[i
]*dt2
+dx
[i
]*dt3
);
872 y
=long(ay
[i
]+by
[i
]*dt1
+cy
[i
]*dt2
+dy
[i
]*dt3
);
873 if (x
<MinKoord
) x
=MinKoord
; if (x
>MaxKoord
) x
=MaxKoord
;
874 if (y
<MinKoord
) y
=MinKoord
; if (y
>MaxKoord
) y
=MaxKoord
;
875 if (rPoly
.GetSize()<PolyMax
) {
876 rPoly
.SetSize(rPoly
.GetSize()+1);
877 rPoly
.SetPoint(Point(short(x
),short(y
)),rPoly
.GetSize()-1);
879 bOk
=FALSE
; // Fehler: Polygon wird zu gross
882 } // Ende von Teilpolynom
883 i
++; // naechstes Teilpolynom
895 } // Ende von if (bOk)