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

Generated by: LCOV version 1.10