LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/filter - sgvspln.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 165 279 59.1 %
Date: 2012-12-27 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include <math.h>
      22             : 
      23             : 
      24             : #include <tools/poly.hxx>
      25             : 
      26             : extern "C" {
      27             : 
      28             : /*.pn 277 */
      29             : /*.hlAnhang: C - Programme*/
      30             : /*.hrKonstanten- und Macro-Definitionen*/
      31             : /*.fe Die Include-Datei u_const.h ist in das Verzeichnis zu stellen,  */
      32             : /*.fe wo der Compiler nach Include-Dateien sucht.                     */
      33             : 
      34             : 
      35             : /*-----------------------  FILE u_const.h  ---------------------------*/
      36             : 
      37             : #define IEEE
      38             : 
      39             : /* IEEE - Norm fuer die Darstellung von Gleitkommazahlen:
      40             : 
      41             :       8 Byte lange Gleitkommazahlen, mit
      42             : 
      43             :      53 Bit Mantisse  ==> Mantissenbereich:    2 hoch 52 versch. Zahlen
      44             :                                                mit 0.1 <= Zahl < 1.0,
      45             :                                                1 Vorzeichen-Bit
      46             :      11 Bit Exponent  ==> Exponentenbereich:  -1024...+1023
      47             : 
      48             :    Die 1. Zeile ( #define IEEE ) ist zu loeschen, falls die Maschine
      49             :    bzw. der Compiler keine Gleitpunktzahlen gemaess der IEEE-Norm
      50             :    benutzt. Zusaetzlich muessen die Zahlen  MAXEXPON, MINEXPON
      51             :    (s.u.) angepasst werden.
      52             :    */
      53             : 
      54             : #ifdef IEEE         /*----------- Falls IEEE Norm --------------------*/
      55             : 
      56             : #define MACH_EPS  2.220446049250313e-016   /* Maschinengenauigkeit    */
      57             :                                            /* IBM-AT:  = 2 hoch -52   */
      58             : /* MACH_EPS ist die kleinste positive, auf der Maschine darstellbare
      59             :    Zahl x, die der Bedingung genuegt: 1.0 + x > 1.0                   */
      60             : 
      61             : #define EPSQUAD   4.930380657631324e-032
      62             : #define EPSROOT   1.490116119384766e-008
      63             : 
      64             : #define POSMAX    8.98846567431158e+307    /* groesste positive Zahl  */
      65             : #define POSMIN    5.56268464626800e-309    /* kleinste positive Zahl  */
      66             : #define MAXROOT   9.48075190810918e+153
      67             : 
      68             : #define BASIS     2                        /* Basis der Zahlendarst.  */
      69             : #ifndef PI
      70             : #define PI        3.141592653589793e+000
      71             : #endif
      72             : #define EXP_1     2.718281828459045e+000
      73             : 
      74             : #else               /*------------------ sonst -----------------------*/
      75             : 
      76             : double exp  (double);
      77             : double atan (double);
      78             : double pow  (double,double);
      79             : double sqrt (double);
      80             : 
      81             : double masch()            /* MACH_EPS maschinenunabhaengig bestimmen  */
      82             : {
      83             :   double eps = 1.0, x = 2.0, y = 1.0;
      84             :   while ( y < x )
      85             :     { eps *= 0.5;
      86             :       x = 1.0 + eps;
      87             :     }
      88             :   eps *= 2.0; return (eps);
      89             : }
      90             : 
      91             : short basis()             /* BASIS maschinenunabhaengig bestimmen     */
      92             : {
      93             :   double x = 1.0, one = 1.0, b = 1.0;
      94             : 
      95             :   while ( (x + one) - x == one ) x *= 2.0;
      96             :   while ( (x + b) == x ) b *= 2.0;
      97             : 
      98             :   return ( (short) ((x + b) - x) );
      99             : }
     100             : 
     101             : #define BASIS     basis()                  /* Basis der Zahlendarst.  */
     102             : 
     103             : /* Falls die Maschine (der Compiler) keine IEEE-Darstellung fuer
     104             :    Gleitkommazahlen nutzt, muessen die folgenden 2 Konstanten an-
     105             :    gepasst werden.
     106             :    */
     107             : 
     108             : #define MAXEXPON  1023.0                   /* groesster Exponent      */
     109             : #define MINEXPON -1024.0                   /* kleinster Exponent      */
     110             : 
     111             : 
     112             : #define MACH_EPS  masch()
     113             : #define EPSQUAD   MACH_EPS * MACH_EPS
     114             : #define EPSROOT   sqrt(MACH_EPS)
     115             : 
     116             : #define POSMAX    pow ((double) BASIS, MAXEXPON)
     117             : #define POSMIN    pow ((double) BASIS, MINEXPON)
     118             : #define MAXROOT   sqrt(POSMAX)
     119             : 
     120             : #define PI        4.0 * atan (1.0)
     121             : #define EXP_1     exp(1.0)
     122             : 
     123             : #endif              /*-------------- ENDE ifdef ----------------------*/
     124             : 
     125             : 
     126             : #define NEGMAX   -POSMIN                   /* groesste negative Zahl  */
     127             : #define NEGMIN   -POSMAX                   /* kleinste negative Zahl  */
     128             : 
     129             : /* Definition von Funktionsmakros:
     130             :    */
     131             : 
     132             : #define abs(X) ((X) >= 0  ?  (X) : -(X))       /* Absolutbetrag von X */
     133             : #define sign(X, Y) (Y < 0 ? -abs(X) : abs(X))  /* Vorzeichen von      */
     134             :                                                /* Y mal abs(X)        */
     135             : #define sqr(X) ((X) * (X))                     /* Quadrat von X       */
     136             : 
     137             : /*-------------------  ENDE FILE u_const.h  --------------------------*/
     138             : 
     139             : 
     140             : 
     141             : 
     142             : 
     143             : 
     144             : 
     145             : 
     146             : 
     147             : /*.HL Anhang: C - Programme*/
     148             : /*.HRGleichungssysteme fuer Tridiagonalmatrizen*/
     149             : 
     150             : /*.FE  P 3.7 TRIDIAGONALE GLEICHUNGSSYSTEME*/
     151             : 
     152             : 
     153             : /*----------------------   MODUL TRIDIAGONAL  ------------------------*/
     154             : 
     155           0 : sal_uInt16 TriDiagGS(sal_Bool rep, sal_uInt16 n, double* lower,
     156             :                  double* diag, double* upper, double* b)
     157             :                                               /************************/
     158             :                                               /* GAUSS-Verfahren fuer */
     159             :                                               /* Tridiagonalmatrizen  */
     160             :                                               /************************/
     161             : 
     162             : /*====================================================================*/
     163             : /*                                                                    */
     164             : /*  trdiag bestimmt die Loesung x des linearen Gleichungssystems      */
     165             : /*  A * x = b mit tridiagonaler n x n Koeffizientenmatrix A, die in   */
     166             : /*  den 3 Vektoren lower, upper und diag wie folgt abgespeichert ist: */
     167             : /*                                                                    */
     168             : /*       ( diag[0]  upper[0]    0        0  .   .     .   0      )    */
     169             : /*       ( lower[1] diag[1]   upper[1]   0      .     .   .      )    */
     170             : /*       (   0      lower[2]  diag[2]  upper[2]   0       .      )    */
     171             : /*  A =  (   .        0       lower[3]  .     .       .          )    */
     172             : /*       (   .          .           .        .     .      0      )    */
     173             : /*       (   .             .            .        .      .        )    */
     174             : /*       (                   .             .        . upper[n-2] )    */
     175             : /*       (   0 .   .    .       0        lower[n-1]   diag[n-1]  )    */
     176             : /*                                                                    */
     177             : /*====================================================================*/
     178             : /*                                                                    */
     179             : /*   Anwendung:                                                       */
     180             : /*   =========                                                        */
     181             : /*      Vorwiegend fuer diagonaldominante Tridiagonalmatrizen, wie    */
     182             : /*      sie bei der Spline-Interpolation auftreten.                   */
     183             : /*      Fuer diagonaldominante Matrizen existiert immer eine LU-      */
     184             : /*      Zerlegung; fuer nicht diagonaldominante Tridiagonalmatrizen   */
     185             : /*      sollte die Funktion band vorgezogen werden, da diese mit      */
     186             : /*      Spaltenpivotsuche arbeitet und daher numerisch stabiler ist.  */
     187             : /*                                                                    */
     188             : /*====================================================================*/
     189             : /*                                                                    */
     190             : /*   Eingabeparameter:                                                */
     191             : /*   ================                                                 */
     192             : /*      n        Dimension der Matrix ( > 1 )  sal_uInt16 n               */
     193             : /*                                                                    */
     194             : /*      lower    untere Nebendiagonale         double lower[n]        */
     195             : /*      diag     Hauptdiagonale                double diag[n]         */
     196             : /*      upper    obere Nebendiagonale          double upper[n]        */
     197             : /*                                                                    */
     198             : /*               bei rep != 0 enthalten lower, diag und upper die     */
     199             : /*               Dreieckzerlegung der Ausgangsmatrix.                 */
     200             : /*                                                                    */
     201             : /*      b        rechte Seite des Systems      double b[n]            */
     202             : /*      rep      = 0  erstmaliger Aufruf       sal_Bool rep               */
     203             : /*               !=0  wiederholter Aufruf                             */
     204             : /*                    fuer gleiche Matrix,                            */
     205             : /*                    aber verschiedenes b.                           */
     206             : /*                                                                    */
     207             : /*   Ausgabeparameter:                                                */
     208             : /*   ================                                                 */
     209             : /*      b        Loesungsvektor des Systems;   double b[n]            */
     210             : /*               die urspruengliche rechte Seite wird ueberspeichert  */
     211             : /*                                                                    */
     212             : /*      lower    ) enthalten bei rep = 0 die Zerlegung der Matrix;    */
     213             : /*      diag     ) die urspruenglichen Werte von lower u. diag werden */
     214             : /*      upper    ) ueberschrieben                                     */
     215             : /*                                                                    */
     216             : /*   Die Determinante der Matrix ist bei rep = 0 durch                */
     217             : /*      det A = diag[0] * ... * diag[n-1] bestimmt.                   */
     218             : /*                                                                    */
     219             : /*   Rueckgabewert:                                                   */
     220             : /*   =============                                                    */
     221             : /*      = 0      alles ok                                             */
     222             : /*      = 1      n < 2 gewaehlt                                       */
     223             : /*      = 2      Die Dreieckzerlegung der Matrix existiert nicht      */
     224             : /*                                                                    */
     225             : /*====================================================================*/
     226             : /*                                                                    */
     227             : /*   Benutzte Funktionen:                                             */
     228             : /*   ===================                                              */
     229             : /*                                                                    */
     230             : /*   Aus der C Bibliothek: fabs()                                     */
     231             : /*                                                                    */
     232             : /*====================================================================*/
     233             : 
     234             : /*.cp 5 */
     235             : {
     236             :  sal_uInt16 i;
     237             :  short  j;
     238             : 
     239             : // double fabs(double);
     240             : 
     241           0 :  if ( n < 2 ) return(1);                    /*  n mindestens 2        */
     242             : 
     243             :                                             /*  Wenn rep = 0 ist,     */
     244             :                                             /*  Dreieckzerlegung der  */
     245           0 :  if (rep == 0)                              /*  Matrix u. det be-     */
     246             :    {                                        /*  stimmen               */
     247           0 :      for (i = 1; i < n; i++)
     248           0 :        { if ( fabs(diag[i-1]) < MACH_EPS )  /*  Wenn ein diag[i] = 0  */
     249           0 :            return(2);                       /*  ist, ex. keine Zerle- */
     250           0 :          lower[i] /= diag[i-1];             /*  gung.                 */
     251           0 :          diag[i] -= lower[i] * upper[i-1];
     252             :        }
     253             :     }
     254             : 
     255           0 :  if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
     256             : 
     257           0 :  for (i = 1; i < n; i++)                   /*  Vorwaertselimination  */
     258           0 :     b[i] -= lower[i] * b[i-1];
     259             : 
     260           0 :  b[n-1] /= diag[n-1];                      /* Rueckwaertselimination */
     261           0 :  for (j = n-2; j >= 0; j--) {
     262           0 :     i=j;
     263           0 :     b[i] = ( b[i] - upper[i] * b[i+1] ) / diag[i];
     264             :  }
     265           0 :  return(0);
     266             : }
     267             : 
     268             : /*-----------------------  ENDE TRIDIAGONAL  -------------------------*/
     269             : 
     270             : 
     271             : 
     272             : 
     273             : 
     274             : 
     275             : 
     276             : 
     277             : 
     278             : /*.HL Anhang: C - Programme*/
     279             : /*.HRGleichungssysteme mit zyklisch tridiagonalen Matrizen*/
     280             : 
     281             : /*.FE  P 3.8  SYSTEME MIT ZYKLISCHEN TRIDIAGONALMATRIZEN */
     282             : 
     283             : 
     284             : /*----------------  MODUL ZYKLISCH TRIDIAGONAL  ----------------------*/
     285             : 
     286             : 
     287           6 : sal_uInt16 ZyklTriDiagGS(sal_Bool rep, sal_uInt16 n, double* lower, double* diag,
     288             :                      double* upper, double* lowrow, double* ricol, double* b)
     289             :                                         /******************************/
     290             :                                         /* Systeme mit zyklisch tri-  */
     291             :                                         /* diagonalen Matrizen        */
     292             :                                         /******************************/
     293             : 
     294             : /*====================================================================*/
     295             : /*                                                                    */
     296             : /*  tzdiag bestimmt die Loesung x des linearen Gleichungssystems      */
     297             : /*  A * x = b mit zyklisch tridiagonaler n x n Koeffizienten-         */
     298             : /*  matrix A, die in den 5 Vektoren lower, upper, diag, lowrow und    */
     299             : /*  ricol wie folgt abgespeichert ist:                                */
     300             : /*                                                                    */
     301             : /*       ( diag[0]  upper[0]    0        0  .   . 0   ricol[0]   )    */
     302             : /*       ( lower[1] diag[1]   upper[1]   0      .     .   0      )    */
     303             : /*       (   0      lower[2]  diag[2]  upper[2]   0       .      )    */
     304             : /*  A =  (   .        0       lower[3]  .     .       .   .      )    */
     305             : /*       (   .          .           .        .     .      0      )    */
     306             : /*       (   .             .            .        .      .        )    */
     307             : /*       (   0               .             .        . upper[n-2] )    */
     308             : /*       ( lowrow[0]  0 .  .    0        lower[n-1]   diag[n-1]  )    */
     309             : /*                                                                    */
     310             : /*  Speicherplatz fuer lowrow[1],..,lowrow[n-3] und ricol[1],...,     */
     311             : /*  ricol[n-3] muss zusaetzlich bereitgestellt werden, da dieser      */
     312             : /*  fuer die Aufnahme der Zerlegungsmatrix verfuegbar sein muss, die  */
     313             : /*  auf die 5 genannten Vektoren ueberspeichert wird.                 */
     314             : /*                                                                    */
     315             : /*====================================================================*/
     316             : /*                                                                    */
     317             : /*   Anwendung:                                                       */
     318             : /*   =========                                                        */
     319             : /*      Vorwiegend fuer diagonaldominante zyklische Tridiagonalmatri- */
     320             : /*      zen wie sie bei der Spline-Interpolation auftreten.           */
     321             : /*      Fuer diagonaldominante Matrizen existiert immer eine LU-      */
     322             : /*      Zerlegung.                                                    */
     323             : /*                                                                    */
     324             : /*====================================================================*/
     325             : /*                                                                    */
     326             : /*   Eingabeparameter:                                                */
     327             : /*   ================                                                 */
     328             : /*      n        Dimension der Matrix ( > 2 )  sal_uInt16 n               */
     329             : /*      lower    untere Nebendiagonale         double lower[n]        */
     330             : /*      diag     Hauptdiagonale                double diag[n]         */
     331             : /*      upper    obere Nebendiagonale          double upper[n]        */
     332             : /*      b        rechte Seite des Systems      double b[n]            */
     333             : /*      rep      = 0  erstmaliger Aufruf       sal_Bool rep               */
     334             : /*               !=0  wiederholter Aufruf                             */
     335             : /*                    fuer gleiche Matrix,                            */
     336             : /*                    aber verschiedenes b.                           */
     337             : /*                                                                    */
     338             : /*   Ausgabeparameter:                                                */
     339             : /*   ================                                                 */
     340             : /*      b        Loesungsvektor des Systems,   double b[n]            */
     341             : /*               die urspruengliche rechte Seite wird ueberspeichert  */
     342             : /*                                                                    */
     343             : /*      lower    ) enthalten bei rep = 0 die Zerlegung der Matrix;    */
     344             : /*      diag     ) die urspruenglichen Werte von lower u. diag werden */
     345             : /*      upper    ) ueberschrieben                                     */
     346             : /*      lowrow   )                             double lowrow[n-2]     */
     347             : /*      ricol    )                             double ricol[n-2]      */
     348             : /*                                                                    */
     349             : /*   Die Determinante der Matrix ist bei rep = 0 durch                */
     350             : /*      det A = diag[0] * ... * diag[n-1]     bestimmt.               */
     351             : /*                                                                    */
     352             : /*   Rueckgabewert:                                                   */
     353             : /*   =============                                                    */
     354             : /*      = 0      alles ok                                             */
     355             : /*      = 1      n < 3 gewaehlt                                       */
     356             : /*      = 2      Die Zerlegungsmatrix existiert nicht                 */
     357             : /*                                                                    */
     358             : /*====================================================================*/
     359             : /*                                                                    */
     360             : /*   Benutzte Funktionen:                                             */
     361             : /*   ===================                                              */
     362             : /*                                                                    */
     363             : /*   Aus der C Bibliothek: fabs()                                     */
     364             : /*                                                                    */
     365             : /*====================================================================*/
     366             : 
     367             : /*.cp 5 */
     368             : {
     369             :  double temp;  // fabs(double);
     370             :  sal_uInt16 i;
     371             :  short  j;
     372             : 
     373           6 :  if ( n < 3 ) return(1);
     374             : 
     375           6 :  if (rep == 0)                              /*  Wenn rep = 0 ist,     */
     376             :    {                                        /*  Zerlegung der         */
     377           6 :      lower[0] = upper[n-1] = 0.0;           /*  Matrix berechnen.     */
     378             : 
     379           6 :      if ( fabs (diag[0]) < MACH_EPS ) return(2);
     380             :                                           /* Ist ein Diagonalelement  */
     381           6 :      temp = 1.0 / diag[0];                /* betragsmaessig kleiner   */
     382           6 :      upper[0] *= temp;                    /* MACH_EPS, so ex. keine   */
     383           6 :      ricol[0] *= temp;                    /* Zerlegung.               */
     384             : 
     385          66 :      for (i = 1; i < n-2; i++)
     386          60 :        { diag[i] -= lower[i] * upper[i-1];
     387          60 :          if ( fabs(diag[i]) < MACH_EPS ) return(2);
     388          60 :          temp = 1.0 / diag[i];
     389          60 :          upper[i] *= temp;
     390          60 :          ricol[i] = -lower[i] * ricol[i-1] * temp;
     391             :        }
     392             : 
     393           6 :      diag[n-2] -= lower[n-2] * upper[n-3];
     394           6 :      if ( fabs(diag[n-2]) < MACH_EPS ) return(2);
     395             : 
     396          66 :      for (i = 1; i < n-2; i++)
     397          60 :        lowrow[i] = -lowrow[i-1] * upper[i-1];
     398             : 
     399           6 :      lower[n-1] -= lowrow[n-3] * upper[n-3];
     400           6 :      upper[n-2] = ( upper[n-2] - lower[n-2] * ricol[n-3] ) / diag[n-2];
     401             : 
     402          72 :      for (temp = 0.0, i = 0; i < n-2; i++)
     403          66 :        temp -= lowrow[i] * ricol[i];
     404           6 :      diag[n-1] += temp - lower[n-1] * upper[n-2];
     405             : 
     406           6 :      if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
     407             :    }  /* end if ( rep == 0 ) */
     408             : 
     409           6 :  b[0] /= diag[0];                          /* Vorwaertselemination    */
     410          72 :  for (i = 1; i < n-1; i++)
     411          66 :    b[i] = ( b[i] - b[i-1] * lower[i] ) / diag[i];
     412             : 
     413          72 :  for (temp = 0.0, i = 0; i < n-2; i++)
     414          66 :    temp -= lowrow[i] * b[i];
     415             : 
     416           6 :  b[n-1] = ( b[n-1] + temp - lower[n-1] * b[n-2] ) / diag[n-1];
     417             : 
     418           6 :  b[n-2] -= b[n-1] * upper[n-2];            /* Rueckwaertselimination  */
     419          72 :  for (j = n-3; j >= 0; j--) {
     420          66 :    i=j;
     421          66 :    b[i] -= upper[i] * b[i+1] + ricol[i] * b[n-1];
     422             :    }
     423           6 :  return(0);
     424             : }
     425             : 
     426             : /*------------------  ENDE ZYKLISCH TRIDIAGONAL  ---------------------*/
     427             : 
     428             : 
     429             : } // extern "C"
     430             : 
     431             : 
     432             : /*************************************************************************
     433             : |*
     434             : |*    NaturalSpline()
     435             : |*
     436             : |*    Beschreibung      Berechnet die Koeffizienten eines natuerlichen
     437             : |*                      kubischen Polynomsplines mit n Stuetzstellen.
     438             : |*
     439             : *************************************************************************/
     440             : 
     441           0 : sal_uInt16 NaturalSpline(sal_uInt16 n, double* x, double* y,
     442             :                      double Marg0, double MargN,
     443             :                      sal_uInt8 MargCond,
     444             :                      double* b, double* c, double* d)
     445             : {
     446             :     sal_uInt16  i;
     447             :     double* a;
     448             :     double* h;
     449             :     sal_uInt16  error;
     450             : 
     451           0 :     if (n<2) return 1;
     452           0 :     if ( (MargCond & ~3) ) return 2;
     453           0 :     a=new double[n+1];
     454           0 :     h=new double[n+1];
     455           0 :     for (i=0;i<n;i++) {
     456           0 :         h[i]=x[i+1]-x[i];
     457           0 :         if (h[i]<=0.0) { delete[] a; delete[] h; return 1; }
     458             :     }
     459           0 :     for (i=0;i<n-1;i++) {
     460           0 :         a[i]=3.0*((y[i+2]-y[i+1])/h[i+1]-(y[i+1]-y[i])/h[i]);
     461           0 :         b[i]=h[i];
     462           0 :         c[i]=h[i+1];
     463           0 :         d[i]=2.0*(h[i]+h[i+1]);
     464             :     }
     465           0 :     switch (MargCond) {
     466             :         case 0: {
     467           0 :             if (n==2) {
     468           0 :                 a[0]=a[0]/3.0;
     469           0 :                 d[0]=d[0]*0.5;
     470             :             } else {
     471           0 :                 a[0]  =a[0]*h[1]/(h[0]+h[1]);
     472           0 :                 a[n-2]=a[n-2]*h[n-2]/(h[n-1]+h[n-2]);
     473           0 :                 d[0]  =d[0]-h[0];
     474           0 :                 d[n-2]=d[n-2]-h[n-1];
     475           0 :                 c[0]  =c[0]-h[0];
     476           0 :                 b[n-2]=b[n-2]-h[n-1];
     477             :             }
     478             :         }
     479             :         case 1: {
     480           0 :             a[0]  =a[0]-1.5*((y[1]-y[0])/h[0]-Marg0);
     481           0 :             a[n-2]=a[n-2]-1.5*(MargN-(y[n]-y[n-1])/h[n-1]);
     482           0 :             d[0]  =d[0]-h[0]*0.5;
     483           0 :             d[n-2]=d[n-2]-h[n-1]*0.5;
     484             :         }
     485             :         case 2: {
     486           0 :             a[0]  =a[0]-h[0]*Marg0*0.5;
     487           0 :             a[n-2]=a[n-2]-h[n-1]*MargN*0.5;
     488             :         }
     489             :         case 3: {
     490           0 :             a[0]  =a[0]+Marg0*h[0]*h[0]*0.5;
     491           0 :             a[n-2]=a[n-2]-MargN*h[n-1]*h[n-1]*0.5;
     492           0 :             d[0]  =d[0]+h[0];
     493           0 :             d[n-2]=d[n-2]+h[n-1];
     494             :         }
     495             :     } // switch MargCond
     496           0 :     if (n==2) {
     497           0 :         c[1]=a[0]/d[0];
     498             :     } else {
     499           0 :         error=TriDiagGS(sal_False,n-1,b,d,c,a);
     500           0 :         if (error!=0) { delete[] a; delete[] h; return error+2; }
     501           0 :         for (i=0;i<n-1;i++) c[i+1]=a[i];
     502             :     }
     503           0 :     switch (MargCond) {
     504             :         case 0: {
     505           0 :             if (n==2) {
     506           0 :                 c[2]=c[1];
     507           0 :                 c[0]=c[1];
     508             :             } else {
     509           0 :                 c[0]=c[1]+h[0]*(c[1]-c[2])/h[1];
     510           0 :                 c[n]=c[n-1]+h[n-1]*(c[n-1]-c[n-2])/h[n-2];
     511             :             }
     512             :         }
     513             :         case 1: {
     514           0 :             c[0]=1.5*((y[1]-y[0])/h[0]-Marg0);
     515           0 :             c[0]=(c[0]-c[1]*h[0]*0.5)/h[0];
     516           0 :             c[n]=1.5*((y[n]-y[n-1])/h[n-1]-MargN);
     517           0 :             c[n]=(c[n]-c[n-1]*h[n-1]*0.5)/h[n-1];
     518             :         }
     519             :         case 2: {
     520           0 :             c[0]=Marg0*0.5;
     521           0 :             c[n]=MargN*0.5;
     522             :         }
     523             :         case 3: {
     524           0 :             c[0]=c[1]-Marg0*h[0]*0.5;
     525           0 :             c[n]=c[n-1]+MargN*h[n-1]*0.5;
     526             :         }
     527             :     } // switch MargCond
     528           0 :     for (i=0;i<n;i++) {
     529           0 :         b[i]=(y[i+1]-y[i])/h[i]-h[i]*(c[i+1]+2.0*c[i])/3.0;
     530           0 :         d[i]=(c[i+1]-c[i])/(3.0*h[i]);
     531             :     }
     532           0 :     delete[] a;
     533           0 :     delete[] h;
     534           0 :     return 0;
     535             : }
     536             : 
     537             : 
     538             : /*************************************************************************
     539             : |*
     540             : |*    PeriodicSpline()
     541             : |*
     542             : |*    Beschreibung      Berechnet die Koeffizienten eines periodischen
     543             : |*                      kubischen Polynomsplines mit n Stuetzstellen.
     544             : |*
     545             : *************************************************************************/
     546             : 
     547             : 
     548           6 : sal_uInt16 PeriodicSpline(sal_uInt16 n, double* x, double* y,
     549             :                       double* b, double* c, double* d)
     550             : {                     // Arrays muessen von [0..n] dimensioniert sein!
     551             :     sal_uInt16  Error;
     552             :     sal_uInt16  i,im1,nm1; //integer
     553             :     double  hr,hl;
     554             :     double* a;
     555             :     double* lowrow;
     556             :     double* ricol;
     557             : 
     558           6 :     if (n<2) return 4;
     559           6 :     nm1=n-1;
     560           6 :     for (i=0;i<=nm1;i++) if (x[i+1]<=x[i]) return 2; // muss streng nonoton fallend sein!
     561           6 :     if (y[n]!=y[0]) return 3; // Anfang muss gleich Ende sein!
     562             : 
     563           6 :     a     =new double[n+1];
     564           6 :     lowrow=new double[n+1];
     565           6 :     ricol =new double[n+1];
     566             : 
     567           6 :     if (n==2) {
     568           0 :         c[1]=3.0*((y[2]-y[1])/(x[2]-x[1]));
     569           0 :         c[1]=c[1]-3.0*((y[i]-y[0])/(x[1]-x[0]));
     570           0 :         c[1]=c[1]/(x[2]-x[0]);
     571           0 :         c[2]=-c[1];
     572             :     } else {
     573          78 :         for (i=1;i<=nm1;i++) {
     574          72 :             im1=i-1;
     575          72 :             hl=x[i]-x[im1];
     576          72 :             hr=x[i+1]-x[i];
     577          72 :             b[im1]=hl;
     578          72 :             d[im1]=2.0*(hl+hr);
     579          72 :             c[im1]=hr;
     580          72 :             a[im1]=3.0*((y[i+1]-y[i])/hr-(y[i]-y[im1])/hl);
     581             :         }
     582           6 :         hl=x[n]-x[nm1];
     583           6 :         hr=x[1]-x[0];
     584           6 :         b[nm1]=hl;
     585           6 :         d[nm1]=2.0*(hl+hr);
     586           6 :         lowrow[0]=hr;
     587           6 :         ricol[0]=hr;
     588           6 :         a[nm1]=3.0*((y[1]-y[0])/hr-(y[n]-y[nm1])/hl);
     589           6 :         Error=ZyklTriDiagGS(sal_False,n,b,d,c,lowrow,ricol,a);
     590           6 :         if ( Error != 0 )
     591             :         {
     592           0 :             delete[] a;
     593           0 :             delete[] lowrow;
     594           0 :             delete[] ricol;
     595           0 :             return(Error+4);
     596             :         }
     597           6 :         for (i=0;i<=nm1;i++) c[i+1]=a[i];
     598             :     }
     599           6 :     c[0]=c[n];
     600          84 :     for (i=0;i<=nm1;i++) {
     601          78 :         hl=x[i+1]-x[i];
     602          78 :         b[i]=(y[i+1]-y[i])/hl;
     603          78 :         b[i]=b[i]-hl*(c[i+1]+2.0*c[i])/3.0;
     604          78 :         d[i]=(c[i+1]-c[i])/hl/3.0;
     605             :     }
     606           6 :     delete[] a;
     607           6 :     delete[] lowrow;
     608           6 :     delete[] ricol;
     609           6 :     return 0;
     610             : }
     611             : 
     612             : 
     613             : 
     614             : /*************************************************************************
     615             : |*
     616             : |*    ParaSpline()
     617             : |*
     618             : |*    Beschreibung      Berechnet die Koeffizienten eines parametrischen
     619             : |*                      natuerlichen oder periodischen kubischen
     620             : |*                      Polynomsplines mit n Stuetzstellen.
     621             : |*
     622             : *************************************************************************/
     623             : 
     624           3 : sal_uInt16 ParaSpline(sal_uInt16 n, double* x, double* y, sal_uInt8 MargCond,
     625             :                   double Marg01, double Marg02,
     626             :                   double MargN1, double MargN2,
     627             :                   sal_Bool CondT, double* T,
     628             :                   double* bx, double* cx, double* dx,
     629             :                   double* by, double* cy, double* dy)
     630             : {
     631             :     sal_uInt16 Error;
     632             :     sal_uInt16 i;
     633             :     double deltX,deltY,delt,
     634           3 :            alphX = 0,alphY = 0,
     635           3 :            betX = 0,betY = 0;
     636             : 
     637           3 :     if (n<2) return 1;
     638           3 :     if ((MargCond & ~3) && (MargCond != 4)) return 2; // ungueltige Randbedingung
     639           3 :     if (CondT==sal_False) {
     640           3 :         T[0]=0.0;
     641          42 :         for (i=0;i<n;i++) {
     642          39 :             deltX=x[i+1]-x[i]; deltY=y[i+1]-y[i];
     643          39 :             delt =deltX*deltX+deltY*deltY;
     644          39 :             if (delt<=0.0) return 3;            // zwei identische Punkte nacheinander!
     645          39 :             T[i+1]=T[i]+sqrt(delt);
     646             :         }
     647             :     }
     648           3 :     switch (MargCond) {
     649           0 :         case 0: break;
     650             :         case 1: case 2: {
     651           0 :             alphX=Marg01; betX=MargN1;
     652           0 :             alphY=Marg02; betY=MargN2;
     653           0 :         } break;
     654             :         case 3: {
     655           3 :             if (x[n]!=x[0]) return 3;
     656           3 :             if (y[n]!=y[0]) return 4;
     657           3 :         } break;
     658             :         case 4: {
     659           0 :             if (abs(Marg01)>=MAXROOT) {
     660           0 :                 alphX=0.0;
     661           0 :                 alphY=sign(1.0,y[1]-y[0]);
     662             :             } else {
     663           0 :                 alphX=sign(sqrt(1.0/(1.0+Marg01*Marg01)),x[1]-x[0]);
     664           0 :                 alphY=alphX*Marg01;
     665             :             }
     666           0 :             if (abs(MargN1)>=MAXROOT) {
     667           0 :                 betX=0.0;
     668           0 :                 betY=sign(1.0,y[n]-y[n-1]);
     669             :             } else {
     670           0 :                 betX=sign(sqrt(1.0/(1.0+MargN1*MargN1)),x[n]-x[n-1]);
     671           0 :                 betY=betX*MargN1;
     672             :             }
     673             :         }
     674             :     } // switch MargCond
     675           3 :     if (MargCond==3) {
     676           3 :         Error=PeriodicSpline(n,T,x,bx,cx,dx);
     677           3 :         if (Error!=0) return(Error+4);
     678           3 :         Error=PeriodicSpline(n,T,y,by,cy,dy);
     679           3 :         if (Error!=0) return(Error+10);
     680             :     } else {
     681           0 :         Error=NaturalSpline(n,T,x,alphX,betX,MargCond,bx,cx,dx);
     682           0 :         if (Error!=0) return(Error+4);
     683           0 :         Error=NaturalSpline(n,T,y,alphY,betY,MargCond,by,cy,dy);
     684           0 :         if (Error!=0) return(Error+9);
     685             :     }
     686           3 :     return 0;
     687             : }
     688             : 
     689             : 
     690             : 
     691             : /*************************************************************************
     692             : |*
     693             : |*    CalcSpline()
     694             : |*
     695             : |*    Beschreibung      Berechnet die Koeffizienten eines parametrischen
     696             : |*                      natuerlichen oder periodischen kubischen
     697             : |*                      Polynomsplines. Die Eckpunkte des uebergebenen
     698             : |*                      Polygons werden als Stuetzstellen angenommen.
     699             : |*                      n liefert die Anzahl der Teilpolynome.
     700             : |*                      Ist die Berechnung fehlerfrei verlaufen, so
     701             : |*                      liefert die Funktion sal_True. Nur in diesem Fall
     702             : |*                      ist Speicher fuer die Koeffizientenarrays
     703             : |*                      allokiert, der dann spaeter vom Aufrufer mittels
     704             : |*                      delete freizugeben ist.
     705             : |*
     706             : *************************************************************************/
     707             : 
     708           3 : sal_Bool CalcSpline(Polygon& rPoly, sal_Bool Periodic, sal_uInt16& n,
     709             :                 double*& ax, double*& ay, double*& bx, double*& by,
     710             :                 double*& cx, double*& cy, double*& dx, double*& dy, double*& T)
     711             : {
     712             :     sal_uInt8   Marg;
     713             :     double Marg01;
     714             :     double MargN1,MargN2;
     715             :     sal_uInt16 i;
     716           3 :     Point  P0(-32768,-32768);
     717           3 :     Point  Pt;
     718             : 
     719           3 :     n=rPoly.GetSize();
     720           3 :     ax=new double[rPoly.GetSize()+2];
     721           3 :     ay=new double[rPoly.GetSize()+2];
     722             : 
     723           3 :     n=0;
     724          42 :     for (i=0;i<rPoly.GetSize();i++) {
     725          39 :         Pt=rPoly.GetPoint(i);
     726          39 :         if (i==0 || Pt!=P0) {
     727          39 :             ax[n]=Pt.X();
     728          39 :             ay[n]=Pt.Y();
     729          39 :             n++;
     730          39 :             P0=Pt;
     731             :         }
     732             :     }
     733             : 
     734           3 :     if (Periodic) {
     735           3 :         Marg=3;
     736           3 :         ax[n]=ax[0];
     737           3 :         ay[n]=ay[0];
     738           3 :         n++;
     739             :     } else {
     740           0 :         Marg=2;
     741             :     }
     742             : 
     743           3 :     bx=new double[n+1];
     744           3 :     by=new double[n+1];
     745           3 :     cx=new double[n+1];
     746           3 :     cy=new double[n+1];
     747           3 :     dx=new double[n+1];
     748           3 :     dy=new double[n+1];
     749           3 :     T =new double[n+1];
     750             : 
     751           3 :     Marg01=0.0;
     752           3 :     MargN1=0.0;
     753           3 :     MargN2=0.0;
     754           3 :     if (n>0) n--; // n Korregieren (Anzahl der Teilpolynome)
     755             : 
     756           3 :     sal_Bool bRet = sal_False;
     757           3 :     if ( ( Marg == 3 && n >= 3 ) || ( Marg == 2 && n >= 2 ) )
     758             :     {
     759           3 :         bRet = ParaSpline(n,ax,ay,Marg,Marg01,Marg01,MargN1,MargN2,sal_False,T,bx,cx,dx,by,cy,dy) == 0;
     760             :     }
     761           3 :     if ( bRet == sal_False )
     762             :     {
     763           0 :         delete[] ax;
     764           0 :         delete[] ay;
     765           0 :         delete[] bx;
     766           0 :         delete[] by;
     767           0 :         delete[] cx;
     768           0 :         delete[] cy;
     769           0 :         delete[] dx;
     770           0 :         delete[] dy;
     771           0 :         delete[] T;
     772           0 :         n=0;
     773             :     }
     774           3 :     return bRet;
     775             : }
     776             : 
     777             : 
     778             : /*************************************************************************
     779             : |*
     780             : |*    Spline2Poly()
     781             : |*
     782             : |*    Beschreibung      Konvertiert einen parametrichen kubischen
     783             : |*                      Polynomspline Spline (natuerlich oder periodisch)
     784             : |*                      in ein angenaehertes Polygon.
     785             : |*                      Die Funktion liefert sal_False, wenn ein Fehler bei
     786             : |*                      der Koeffizientenberechnung aufgetreten ist oder
     787             : |*                      das Polygon zu gross wird (>PolyMax=16380). Im 1.
     788             : |*                      Fall hat das Polygon 0, im 2. Fall PolyMax Punkte.
     789             : |*                      Um Koordinatenueberlaeufe zu vermeiden werden diese
     790             : |*                      auf +/-32000 begrenzt.
     791             : |*
     792             : *************************************************************************/
     793           3 : sal_Bool Spline2Poly(Polygon& rSpln, sal_Bool Periodic, Polygon& rPoly)
     794             : {
     795           3 :     short  MinKoord=-32000; // zur Vermeidung
     796           3 :     short  MaxKoord=32000;  // von Ueberlaeufen
     797             : 
     798             :     double* ax;          // Koeffizienten der Polynome
     799             :     double* ay;
     800             :     double* bx;
     801             :     double* by;
     802             :     double* cx;
     803             :     double* cy;
     804             :     double* dx;
     805             :     double* dy;
     806             :     double* tv;
     807             : 
     808             :     double  Step;        // Schrittweite fuer t
     809             :     double  dt1,dt2,dt3; // Delta t, y, ^3
     810             :     double  t;
     811             :     sal_Bool    bEnde;       // Teilpolynom zu Ende?
     812             :     sal_uInt16  n;           // Anzahl der zu zeichnenden Teilpolynome
     813             :     sal_uInt16  i;           // aktuelles Teilpolynom
     814             :     sal_Bool    bOk;         // noch alles ok?
     815           3 :     sal_uInt16  PolyMax=16380;// Maximale Anzahl von Polygonpunkten
     816             :     long    x,y;
     817             : 
     818           3 :     bOk=CalcSpline(rSpln,Periodic,n,ax,ay,bx,by,cx,cy,dx,dy,tv);
     819           3 :     if (bOk) {
     820           3 :         Step =10;
     821             : 
     822           3 :         rPoly.SetSize(1);
     823           3 :         rPoly.SetPoint(Point(short(ax[0]),short(ay[0])),0); // erster Punkt
     824           3 :         i=0;
     825          45 :         while (i<n) {       // n Teilpolynome malen
     826          39 :             t=tv[i]+Step;
     827          39 :             bEnde=sal_False;
     828       10714 :             while (!bEnde) {  // ein Teilpolynom interpolieren
     829       10636 :                 bEnde=t>=tv[i+1];
     830       10636 :                 if (bEnde) t=tv[i+1];
     831       10636 :                 dt1=t-tv[i]; dt2=dt1*dt1; dt3=dt2*dt1;
     832       10636 :                 x=long(ax[i]+bx[i]*dt1+cx[i]*dt2+dx[i]*dt3);
     833       10636 :                 y=long(ay[i]+by[i]*dt1+cy[i]*dt2+dy[i]*dt3);
     834       10636 :                 if (x<MinKoord) x=MinKoord; if (x>MaxKoord) x=MaxKoord;
     835       10636 :                 if (y<MinKoord) y=MinKoord; if (y>MaxKoord) y=MaxKoord;
     836       10636 :                 if (rPoly.GetSize()<PolyMax) {
     837       10636 :                     rPoly.SetSize(rPoly.GetSize()+1);
     838       10636 :                     rPoly.SetPoint(Point(short(x),short(y)),rPoly.GetSize()-1);
     839             :                 } else {
     840           0 :                     bOk=sal_False; // Fehler: Polygon wird zu gross
     841             :                 }
     842       10636 :                 t=t+Step;
     843             :             } // Ende von Teilpolynom
     844          39 :             i++; // naechstes Teilpolynom
     845             :         }
     846           3 :         delete[] ax;
     847           3 :         delete[] ay;
     848           3 :         delete[] bx;
     849           3 :         delete[] by;
     850           3 :         delete[] cx;
     851           3 :         delete[] cy;
     852           3 :         delete[] dx;
     853           3 :         delete[] dy;
     854           3 :         delete[] tv;
     855           3 :         return bOk;
     856             :     } // Ende von if (bOk)
     857           0 :     rPoly.SetSize(0);
     858           0 :     return sal_False;
     859             : }
     860             : 
     861             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10