LCOV - code coverage report
Current view: top level - vcl/source/filter - sgvspln.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 165 276 59.8 %
Date: 2014-04-11 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             : #include <math.h>
      21             : 
      22             : #include <tools/poly.hxx>
      23             : #include <boost/scoped_array.hpp>
      24             : 
      25             : #include <sgvspln.hxx>
      26             : 
      27             : extern "C" {
      28             : 
      29             : /*.pn 277 */
      30             : /*.hlAppendix: C - programs*/
      31             : /*.hrConstants- and macrodefinitions*/
      32             : /*.fe The include file u_const.h should be stored in the directory,   */
      33             : /*.fe where the compiler searches for include files.                  */
      34             : 
      35             : /*-----------------------  FILE u_const.h  ---------------------------*/
      36             : 
      37             : #define IEEE
      38             : 
      39             : /* IEEE - standard for representation of floating-point numbers:
      40             : 
      41             :      8 byte long floating point numbers with
      42             : 
      43             :     53 bit mantissa  ==> mantissa range:     2^52 different numbers
      44             :                                               with 0.1 <= number < 1.0,
      45             :                                               1 sign-bit
      46             :     11 bit exponent  ==> exponent range:  -1024...+1023
      47             : 
      48             :   The first line (#define IEEE) should be deleted if the machine
      49             :   or the compiler does not use floating-point numbers according
      50             :   to the IEEE standard. In which case also MAXEXPON, MINEXPON (see
      51             :   below) should be adapted.
      52             : */
      53             : 
      54             : #ifdef IEEE         /*-------------- if IEEE norm --------------------*/
      55             : 
      56             : #define MACH_EPS  2.220446049250313e-016      /* machine precision    */
      57             :                                               /* IBM-AT:  = 2^-52    */
      58             : /* MACH_EPS is the smallest positive,  by the machine representable
      59             :    number x, which fulfills the equation: 1.0 + x > 1.0               */
      60             : 
      61             : #define MAXROOT   9.48075190810918e+153
      62             : 
      63             : #else               /*------------------ otherwise--------------------*/
      64             : 
      65             : double exp  (double);
      66             : double atan (double);
      67             : double pow  (double,double);
      68             : double sqrt (double);
      69             : 
      70             : double masch()            /* calculate MACH_EPS machine independence   */
      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;
      78             :   return (eps);
      79             : }
      80             : 
      81             : short basis()              /* calculate BASE machine independence     */
      82             : {
      83             :   double x = 1.0, one = 1.0, b = 1.0;
      84             : 
      85             :   while ( (x + one) - x == one ) x *= 2.0;
      86             :   while ( (x + b) == x ) b *= 2.0;
      87             : 
      88             :   return ( (short) ((x + b) - x) );
      89             : }
      90             : 
      91             : #define BASIS     basis()           /* base of number representation  */
      92             : 
      93             : /* If the machine (the compiler) does not use the IEEE-representation
      94             :    for floating-point numbers, the next 2 constants should be adapted.
      95             :    */
      96             : 
      97             : #define MAXEXPON  1023.0                    /* largest exponent       */
      98             : #define MINEXPON -1024.0                    /* smallest exponent      */
      99             : 
     100             : #define MACH_EPS  masch()
     101             : 
     102             : #define POSMAX    pow ((double) BASIS, MAXEXPON)
     103             : #define MAXROOT   sqrt(POSMAX)
     104             : 
     105             : #endif              /*-------------- END of ifdef --------------------*/
     106             : 
     107             : /* defines for function macros:                                        */
     108             : 
     109             : #define abs(X) ((X) >= 0  ?  (X) : -(X))        /* absolute number  X */
     110             : #define sign(X, Y) (Y < 0 ? -abs(X) : abs(X))   /* sign of Y times    */
     111             :                                                 /* abs(X)             */
     112             : 
     113             : /*--------------------  END of FILE u_const.h  -----------------------*/
     114             : 
     115             : /*.HL appendix: C - programs*/
     116             : /*.HR Systems of equations for tridiagonal matrices*/
     117             : 
     118             : /*.FE  P 3.7 tridiagonal systems of equations */
     119             : 
     120             : /*----------------------   MODULE tridiagonal  -----------------------*/
     121             : 
     122           0 : sal_uInt16 TriDiagGS(bool rep, sal_uInt16 n, double* lower,
     123             :                  double* diag, double* upper, double* b)
     124             :                                              /*************************/
     125             :                                              /* Gaussian methods for  */
     126             :                                              /* tridiagonal matrices  */
     127             :                                              /*************************/
     128             : 
     129             : /*====================================================================*/
     130             : /*                                                                    */
     131             : /*  trdiag determines solution x of the system of linear equations    */
     132             : /*  A * x = b with tridiagonal n x n coefficient matrix A, which is   */
     133             : /*  stored in 3 vectors lower, upper and diag as per below:           */
     134             : /*                                                                    */
     135             : /*       ( diag[0]  upper[0]    0        0  .   .     .   0      )    */
     136             : /*       ( lower[1] diag[1]   upper[1]   0      .     .   .      )    */
     137             : /*       (   0      lower[2]  diag[2]  upper[2]   0       .      )    */
     138             : /*  A =  (   .        0       lower[3]  .     .       .          )    */
     139             : /*       (   .          .           .        .     .      0      )    */
     140             : /*       (   .             .            .        .      .        )    */
     141             : /*       (                   .             .        . upper[n-2] )    */
     142             : /*       (   0 .   .    .       0        lower[n-1]   diag[n-1]  )    */
     143             : /*                                                                    */
     144             : /*====================================================================*/
     145             : /*                                                                    */
     146             : /*   Usage:                                                           */
     147             : /*   ======                                                           */
     148             : /*      Mainly for diagonal determinant triangular matrix, as they    */
     149             : /*      occur in Spline-interpolations.                               */
     150             : /*      For diagonal dominant matrices always a left-upper row        */
     151             : /*      reduction exists; for non diagonal dominant triangular        */
     152             : /*      matrices we should pull forward the function band, as this    */
     153             : /*      works with row pivot searches, which is numerical more stable.*/
     154             : /*                                                                    */
     155             : /*====================================================================*/
     156             : /*                                                                    */
     157             : /*   Input parameters:                                                */
     158             : /*   ================                                                 */
     159             : /*      n        dimension of the matrix ( > 1 )  sal_uInt16 n        */
     160             : /*                                                                    */
     161             : /*      lower    lower antidiagonal               double lower[n]     */
     162             : /*      diag     main diagonal                    double diag[n]      */
     163             : /*      upper    upper antidiagonal               double upper[n]     */
     164             : /*                                                                    */
     165             : /*               for rep = true lower, diag and upper contain the     */
     166             : /*               triangulation of the start matrix.                   */
     167             : /*                                                                    */
     168             : /*      b        right side of equation     double b[n]               */
     169             : /*      rep      = false first call         bool rep                  */
     170             : /*               = true  next call                                    */
     171             : /*                    for the same matrix,                            */
     172             : /*                    but different b.                                */
     173             : /*                                                                    */
     174             : /*   Output parameters:                                               */
     175             : /*   =================                                                */
     176             : /*      b        solution vector of the system;   double b[n]         */
     177             : /*               the original right side is overwritten               */
     178             : /*                                                                    */
     179             : /*      lower    ) contain for rep = false the decomposition of the   */
     180             : /*      diag     ) matrix; the original values of the lower and       */
     181             : /*      upper    ) diagonals are overwritten                          */
     182             : /*                                                                    */
     183             : /*   The determinant of the matrix is for rep = false defined by      */
     184             : /*      determinant A = diag[0] * ... * diag[n-1]                     */
     185             : /*                                                                    */
     186             : /*   Return value:                                                    */
     187             : /*   =============                                                    */
     188             : /*      = 0      all ok                                               */
     189             : /*      = 1      n < 2 chosen                                         */
     190             : /*      = 2      triangular decomposition of matrix does not exist    */
     191             : /*                                                                    */
     192             : /*====================================================================*/
     193             : /*                                                                    */
     194             : /*   Functions used:                                                  */
     195             : /*   ===============                                                  */
     196             : /*                                                                    */
     197             : /*   From the C library: fabs()                                       */
     198             : /*                                                                    */
     199             : /*====================================================================*/
     200             : 
     201             : /*.cp 5 */
     202             : {
     203             :  sal_uInt16 i;
     204             :  short  j;
     205             : 
     206             : // double fabs(double);
     207             : 
     208           0 :  if ( n < 2 ) return(1);                    /*  n at least 2          */
     209             : 
     210             :                                             /*  if rep = false,       */
     211             :                                             /*  determine the         */
     212             :                                             /*  triangular            */
     213             :                                             /*  decomposition of      */
     214           0 :  if (!rep)                                  /*  matrix and determinant*/
     215             :    {
     216           0 :      for (i = 1; i < n; i++)
     217           0 :        { if ( fabs(diag[i-1]) < MACH_EPS )  /*  do not decompose      */
     218           0 :            return(2);                       /*  if one diag[i] = 0    */
     219           0 :          lower[i] /= diag[i-1];
     220           0 :          diag[i] -= lower[i] * upper[i-1];
     221             :        }
     222             :     }
     223             : 
     224           0 :  if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
     225             : 
     226           0 :  for (i = 1; i < n; i++)                    /* forward elimination    */
     227           0 :     b[i] -= lower[i] * b[i-1];
     228             : 
     229           0 :  b[n-1] /= diag[n-1];                       /* reverse elimination    */
     230           0 :  for (j = n-2; j >= 0; j--) {
     231           0 :     i=j;
     232           0 :     b[i] = ( b[i] - upper[i] * b[i+1] ) / diag[i];
     233             :  }
     234           0 :  return(0);
     235             : }
     236             : 
     237             : /*-----------------------  END OF TRIDIAGONAL  ------------------------*/
     238             : 
     239             : /*.HL Appendix: C - Programs*/
     240             : /*.HRSystems of equations with cyclic tridiagonal matrices*/
     241             : 
     242             : /*.FE  P 3.8  Systems with cyclic tridiagonal matrices    */
     243             : 
     244             : /*----------------  Module cyclic tridiagonal  -----------------------*/
     245             : 
     246           6 : sal_uInt16 ZyklTriDiagGS(bool rep, sal_uInt16 n, double* lower, double* diag,
     247             :                      double* upper, double* lowrow, double* ricol, double* b)
     248             :                                         /******************************/
     249             :                                         /* Systems with cyclic        */
     250             :                                         /* tridiagonal matrices       */
     251             :                                         /******************************/
     252             : 
     253             : /*====================================================================*/
     254             : /*                                                                    */
     255             : /*  tzdiag determines the solution x of the linear equation system    */
     256             : /*  A * x = b with cyclic tridiagonal  n x n coefficient-             */
     257             : /*  matrix A, which is stored in the 5 vectors: lower, upper, diag,   */
     258             : /*  lowrow and ricol as per below:                                    */
     259             : /*                                                                    */
     260             : /*       ( diag[0]  upper[0]    0        0  .   . 0   ricol[0]   )    */
     261             : /*       ( lower[1] diag[1]   upper[1]   0      .     .   0      )    */
     262             : /*       (   0      lower[2]  diag[2]  upper[2]   0       .      )    */
     263             : /*  A =  (   .        0       lower[3]  .     .       .   .      )    */
     264             : /*       (   .          .           .        .     .      0      )    */
     265             : /*       (   .             .            .        .      .        )    */
     266             : /*       (   0               .             .        . upper[n-2] )    */
     267             : /*       ( lowrow[0]  0 .  .    0        lower[n-1]   diag[n-1]  )    */
     268             : /*                                                                    */
     269             : /*  Memory for lowrow[1],..,lowrow[n-3] und ricol[1],...,ricol[n-3]   */
     270             : /*  should be provided separately, as this should be available to     */
     271             : /*  store the decomposition matrix, which is overwritting             */
     272             : /*  the 5 vectors mentioned.                                          */
     273             : /*                                                                    */
     274             : /*====================================================================*/
     275             : /*                                                                    */
     276             : /*   Usage:                                                           */
     277             : /*   ======                                                           */
     278             : /*      Predominantly for diagonal dominant cyclic tridiagonal-       */
     279             : /*      matrices as they occur in spline-interpolations.              */
     280             : /*      For diagonal dominant matices only a LU-decomposition exists. */
     281             : /*                                                                    */
     282             : /*====================================================================*/
     283             : /*                                                                    */
     284             : /*   Input parameters:                                                */
     285             : /*   =================                                                */
     286             : /*      n        Dimension of the matrix ( > 2 )  sal_uInt16 n        */
     287             : /*      lower    lower antidiagonal               double lower[n]     */
     288             : /*      diag     main diagonal                    double diag[n]      */
     289             : /*      upper    upper antidiagonal               double upper[n]     */
     290             : /*      b        right side of the system         double b[n]         */
     291             : /*      rep      = FALSE first call               bool rep            */
     292             : /*               = TRUE  repeated call                                */
     293             : /*                    for equal matrix,                               */
     294             : /*                    but different b.                                */
     295             : /*                                                                    */
     296             : /*   Output parameters:                                               */
     297             : /*   ==================                                               */
     298             : /*      b        solution vector of the system,   double b[n]         */
     299             : /*               the original right side is overwritten               */
     300             : /*                                                                    */
     301             : /*      lower    ) contain for rep = false the solution of the matrix;*/
     302             : /*      diag     ) the original values of lower and diagonal will be  */
     303             : /*      upper    ) overwritten                                        */
     304             : /*      lowrow   )                             double lowrow[n-2]     */
     305             : /*      ricol    )                             double ricol[n-2]      */
     306             : /*                                                                    */
     307             : /*   The determinant of the matrix is for rep = false                 */
     308             : /*      det A = diag[0] * ... * diag[n-1]     defined .               */
     309             : /*                                                                    */
     310             : /*   Return value:                                                    */
     311             : /*   =============                                                    */
     312             : /*      = 0      all ok                                               */
     313             : /*      = 1      n < 3 chosen                                         */
     314             : /*      = 2      Decomposition matrix does not exist                  */
     315             : /*                                                                    */
     316             : /*====================================================================*/
     317             : /*                                                                    */
     318             : /*   Used functions:                                                  */
     319             : /*   ===============                                                  */
     320             : /*                                                                    */
     321             : /*   from the C library: fabs()                                       */
     322             : /*                                                                    */
     323             : /*====================================================================*/
     324             : 
     325             : /*.cp 5 */
     326             : {
     327             :  double temp;  // fabs(double);
     328             :  sal_uInt16 i;
     329             :  short  j;
     330             : 
     331           6 :  if ( n < 3 ) return(1);
     332             : 
     333           6 :  if (!rep)                               /*  If rep = false,          */
     334             :    {                                     /*  calculate decomposition  */
     335           6 :      lower[0] = upper[n-1] = 0.0;        /*  of the matrix.           */
     336             : 
     337           6 :      if ( fabs (diag[0]) < MACH_EPS ) return(2);
     338             :                                          /* Do not decompose if the   */
     339           6 :      temp = 1.0 / diag[0];               /* value of a diagonal       */
     340           6 :      upper[0] *= temp;                   /* element is smaller then   */
     341           6 :      ricol[0] *= temp;                   /* MACH_EPS                  */
     342             : 
     343          66 :      for (i = 1; i < n-2; i++)
     344          60 :        { diag[i] -= lower[i] * upper[i-1];
     345          60 :          if ( fabs(diag[i]) < MACH_EPS ) return(2);
     346          60 :          temp = 1.0 / diag[i];
     347          60 :          upper[i] *= temp;
     348          60 :          ricol[i] = -lower[i] * ricol[i-1] * temp;
     349             :        }
     350             : 
     351           6 :      diag[n-2] -= lower[n-2] * upper[n-3];
     352           6 :      if ( fabs(diag[n-2]) < MACH_EPS ) return(2);
     353             : 
     354          66 :      for (i = 1; i < n-2; i++)
     355          60 :        lowrow[i] = -lowrow[i-1] * upper[i-1];
     356             : 
     357           6 :      lower[n-1] -= lowrow[n-3] * upper[n-3];
     358           6 :      upper[n-2] = ( upper[n-2] - lower[n-2] * ricol[n-3] ) / diag[n-2];
     359             : 
     360          72 :      for (temp = 0.0, i = 0; i < n-2; i++)
     361          66 :        temp -= lowrow[i] * ricol[i];
     362           6 :      diag[n-1] += temp - lower[n-1] * upper[n-2];
     363             : 
     364           6 :      if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
     365             :    }
     366             : 
     367           6 :  b[0] /= diag[0];                          /* forward elimination    */
     368          72 :  for (i = 1; i < n-1; i++)
     369          66 :    b[i] = ( b[i] - b[i-1] * lower[i] ) / diag[i];
     370             : 
     371          72 :  for (temp = 0.0, i = 0; i < n-2; i++)
     372          66 :    temp -= lowrow[i] * b[i];
     373             : 
     374           6 :  b[n-1] = ( b[n-1] + temp - lower[n-1] * b[n-2] ) / diag[n-1];
     375             : 
     376           6 :  b[n-2] -= b[n-1] * upper[n-2];            /* backward elimination   */
     377          72 :  for (j = n-3; j >= 0; j--) {
     378          66 :    i=j;
     379          66 :    b[i] -= upper[i] * b[i+1] + ricol[i] * b[n-1];
     380             :    }
     381           6 :  return(0);
     382             : }
     383             : 
     384             : /*------------------  END of CYCLIC TRIDIAGONAL  ---------------------*/
     385             : 
     386             : } // extern "C"
     387             : 
     388             : /*************************************************************************
     389             : |*
     390             : |*    NaturalSpline()
     391             : |*
     392             : |*    Description       calculates the coefficients of natural
     393             : |*                      cubic splines with n intervals.
     394             : |*
     395             : *************************************************************************/
     396             : 
     397           0 : sal_uInt16 NaturalSpline(sal_uInt16 n, double* x, double* y,
     398             :                      double Marg0, double MargN,
     399             :                      sal_uInt8 MargCond,
     400             :                      double* b, double* c, double* d)
     401             : {
     402             :     sal_uInt16  i;
     403           0 :     boost::scoped_array<double> a;
     404           0 :     boost::scoped_array<double> h;
     405             :     sal_uInt16  error;
     406             : 
     407           0 :     if (n<2) return 1;
     408           0 :     if ( (MargCond & ~3) ) return 2;
     409           0 :     a.reset(new double[n+1]);
     410           0 :     h.reset(new double[n+1]);
     411           0 :     for (i=0;i<n;i++) {
     412           0 :         h[i]=x[i+1]-x[i];
     413           0 :         if (h[i]<=0.0) return 1;
     414             :     }
     415           0 :     for (i=0;i<n-1;i++) {
     416           0 :         a[i]=3.0*((y[i+2]-y[i+1])/h[i+1]-(y[i+1]-y[i])/h[i]);
     417           0 :         b[i]=h[i];
     418           0 :         c[i]=h[i+1];
     419           0 :         d[i]=2.0*(h[i]+h[i+1]);
     420             :     }
     421           0 :     switch (MargCond) {
     422             :         case 0: {
     423           0 :             if (n==2) {
     424           0 :                 a[0]=a[0]/3.0;
     425           0 :                 d[0]=d[0]*0.5;
     426             :             } else {
     427           0 :                 a[0]  =a[0]*h[1]/(h[0]+h[1]);
     428           0 :                 a[n-2]=a[n-2]*h[n-2]/(h[n-1]+h[n-2]);
     429           0 :                 d[0]  =d[0]-h[0];
     430           0 :                 d[n-2]=d[n-2]-h[n-1];
     431           0 :                 c[0]  =c[0]-h[0];
     432           0 :                 b[n-2]=b[n-2]-h[n-1];
     433             :             }
     434             :         }
     435             :         case 1: {
     436           0 :             a[0]  =a[0]-1.5*((y[1]-y[0])/h[0]-Marg0);
     437           0 :             a[n-2]=a[n-2]-1.5*(MargN-(y[n]-y[n-1])/h[n-1]);
     438           0 :             d[0]  =d[0]-h[0]*0.5;
     439           0 :             d[n-2]=d[n-2]-h[n-1]*0.5;
     440             :         }
     441             :         case 2: {
     442           0 :             a[0]  =a[0]-h[0]*Marg0*0.5;
     443           0 :             a[n-2]=a[n-2]-h[n-1]*MargN*0.5;
     444             :         }
     445             :         case 3: {
     446           0 :             a[0]  =a[0]+Marg0*h[0]*h[0]*0.5;
     447           0 :             a[n-2]=a[n-2]-MargN*h[n-1]*h[n-1]*0.5;
     448           0 :             d[0]  =d[0]+h[0];
     449           0 :             d[n-2]=d[n-2]+h[n-1];
     450             :         }
     451             :     } // switch MargCond
     452           0 :     if (n==2) {
     453           0 :         c[1]=a[0]/d[0];
     454             :     } else {
     455           0 :         error=TriDiagGS(false,n-1,b,d,c,a.get());
     456           0 :         if (error!=0) return error+2;
     457           0 :         for (i=0;i<n-1;i++) c[i+1]=a[i];
     458             :     }
     459           0 :     switch (MargCond) {
     460             :         case 0: {
     461           0 :             if (n==2) {
     462           0 :                 c[2]=c[1];
     463           0 :                 c[0]=c[1];
     464             :             } else {
     465           0 :                 c[0]=c[1]+h[0]*(c[1]-c[2])/h[1];
     466           0 :                 c[n]=c[n-1]+h[n-1]*(c[n-1]-c[n-2])/h[n-2];
     467             :             }
     468             :         }
     469             :         case 1: {
     470           0 :             c[0]=1.5*((y[1]-y[0])/h[0]-Marg0);
     471           0 :             c[0]=(c[0]-c[1]*h[0]*0.5)/h[0];
     472           0 :             c[n]=1.5*((y[n]-y[n-1])/h[n-1]-MargN);
     473           0 :             c[n]=(c[n]-c[n-1]*h[n-1]*0.5)/h[n-1];
     474             :         }
     475             :         case 2: {
     476           0 :             c[0]=Marg0*0.5;
     477           0 :             c[n]=MargN*0.5;
     478             :         }
     479             :         case 3: {
     480           0 :             c[0]=c[1]-Marg0*h[0]*0.5;
     481           0 :             c[n]=c[n-1]+MargN*h[n-1]*0.5;
     482             :         }
     483             :     } // switch MargCond
     484           0 :     for (i=0;i<n;i++) {
     485           0 :         b[i]=(y[i+1]-y[i])/h[i]-h[i]*(c[i+1]+2.0*c[i])/3.0;
     486           0 :         d[i]=(c[i+1]-c[i])/(3.0*h[i]);
     487             :     }
     488           0 :     return 0;
     489             : }
     490             : 
     491             : /*************************************************************************
     492             : |*
     493             : |*    PeriodicSpline()
     494             : |*
     495             : |*    Description       calculates the coefficients of periodical
     496             : |*                      cubic splines with n intervals.
     497             : |*
     498             : *************************************************************************/
     499             : 
     500           6 : sal_uInt16 PeriodicSpline(sal_uInt16 n, double* x, double* y,
     501             :                       double* b, double* c, double* d)
     502             : {                     // array dimensions should range from [0..n]!
     503             :     sal_uInt16  Error;
     504             :     sal_uInt16  i,im1,nm1; //integer
     505             :     double  hr,hl;
     506           6 :     boost::scoped_array<double> a;
     507          12 :     boost::scoped_array<double> lowrow;
     508          12 :     boost::scoped_array<double> ricol;
     509             : 
     510           6 :     if (n<2) return 4;
     511           6 :     nm1=n-1;
     512           6 :     for (i=0;i<=nm1;i++) if (x[i+1]<=x[i]) return 2; // should be strictly monotonically decreasing!
     513           6 :     if (y[n]!=y[0]) return 3; // begin and end should be equal!
     514             : 
     515           6 :     a.reset(new double[n+1]);
     516           6 :     lowrow.reset(new double[n+1]);
     517           6 :     ricol.reset(new double[n+1]);
     518             : 
     519           6 :     if (n==2) {
     520           0 :         c[1]=3.0*((y[2]-y[1])/(x[2]-x[1]));
     521           0 :         c[1]=c[1]-3.0*((y[i]-y[0])/(x[1]-x[0]));
     522           0 :         c[1]=c[1]/(x[2]-x[0]);
     523           0 :         c[2]=-c[1];
     524             :     } else {
     525          78 :         for (i=1;i<=nm1;i++) {
     526          72 :             im1=i-1;
     527          72 :             hl=x[i]-x[im1];
     528          72 :             hr=x[i+1]-x[i];
     529          72 :             b[im1]=hl;
     530          72 :             d[im1]=2.0*(hl+hr);
     531          72 :             c[im1]=hr;
     532          72 :             a[im1]=3.0*((y[i+1]-y[i])/hr-(y[i]-y[im1])/hl);
     533             :         }
     534           6 :         hl=x[n]-x[nm1];
     535           6 :         hr=x[1]-x[0];
     536           6 :         b[nm1]=hl;
     537           6 :         d[nm1]=2.0*(hl+hr);
     538           6 :         lowrow[0]=hr;
     539           6 :         ricol[0]=hr;
     540           6 :         a[nm1]=3.0*((y[1]-y[0])/hr-(y[n]-y[nm1])/hl);
     541           6 :         Error=ZyklTriDiagGS(false,n,b,d,c,lowrow.get(),ricol.get(),a.get());
     542           6 :         if ( Error != 0 )
     543             :         {
     544           0 :             return(Error+4);
     545             :         }
     546           6 :         for (i=0;i<=nm1;i++) c[i+1]=a[i];
     547             :     }
     548           6 :     c[0]=c[n];
     549          84 :     for (i=0;i<=nm1;i++) {
     550          78 :         hl=x[i+1]-x[i];
     551          78 :         b[i]=(y[i+1]-y[i])/hl;
     552          78 :         b[i]=b[i]-hl*(c[i+1]+2.0*c[i])/3.0;
     553          78 :         d[i]=(c[i+1]-c[i])/hl/3.0;
     554             :     }
     555          12 :     return 0;
     556             : }
     557             : 
     558             : /*************************************************************************
     559             : |*
     560             : |*    ParaSpline()
     561             : |*
     562             : |*    Description       calculate the coefficients of parametric
     563             : |*                      natural of periodical cubic splines with n intervals
     564             : |*
     565             : *************************************************************************/
     566             : 
     567           3 : sal_uInt16 ParaSpline(sal_uInt16 n, double* x, double* y, sal_uInt8 MargCond,
     568             :                   double Marg01, double Marg02,
     569             :                   double MargN1, double MargN2,
     570             :                   bool CondT, double* T,
     571             :                   double* bx, double* cx, double* dx,
     572             :                   double* by, double* cy, double* dy)
     573             : {
     574             :     sal_uInt16 Error;
     575             :     sal_uInt16 i;
     576             :     double deltX,deltY,delt,
     577           3 :            alphX = 0,alphY = 0,
     578           3 :            betX = 0,betY = 0;
     579             : 
     580           3 :     if (n<2) return 1;
     581           3 :     if ((MargCond & ~3) && (MargCond != 4)) return 2; // invalid boundary condition
     582           3 :     if (!CondT) {
     583           3 :         T[0]=0.0;
     584          42 :         for (i=0;i<n;i++) {
     585          39 :             deltX=x[i+1]-x[i]; deltY=y[i+1]-y[i];
     586          39 :             delt =deltX*deltX+deltY*deltY;
     587          39 :             if (delt<=0.0) return 3;            // two identical adjacent points!
     588          39 :             T[i+1]=T[i]+sqrt(delt);
     589             :         }
     590             :     }
     591           3 :     switch (MargCond) {
     592           0 :         case 0: break;
     593             :         case 1: case 2: {
     594           0 :             alphX=Marg01; betX=MargN1;
     595           0 :             alphY=Marg02; betY=MargN2;
     596           0 :         } break;
     597             :         case 3: {
     598           3 :             if (x[n]!=x[0]) return 3;
     599           3 :             if (y[n]!=y[0]) return 4;
     600           3 :         } break;
     601             :         case 4: {
     602           0 :             if (abs(Marg01)>=MAXROOT) {
     603           0 :                 alphX=0.0;
     604           0 :                 alphY=sign(1.0,y[1]-y[0]);
     605             :             } else {
     606           0 :                 alphX=sign(sqrt(1.0/(1.0+Marg01*Marg01)),x[1]-x[0]);
     607           0 :                 alphY=alphX*Marg01;
     608             :             }
     609           0 :             if (abs(MargN1)>=MAXROOT) {
     610           0 :                 betX=0.0;
     611           0 :                 betY=sign(1.0,y[n]-y[n-1]);
     612             :             } else {
     613           0 :                 betX=sign(sqrt(1.0/(1.0+MargN1*MargN1)),x[n]-x[n-1]);
     614           0 :                 betY=betX*MargN1;
     615             :             }
     616             :         }
     617             :     } // switch MargCond
     618           3 :     if (MargCond==3) {
     619           3 :         Error=PeriodicSpline(n,T,x,bx,cx,dx);
     620           3 :         if (Error!=0) return(Error+4);
     621           3 :         Error=PeriodicSpline(n,T,y,by,cy,dy);
     622           3 :         if (Error!=0) return(Error+10);
     623             :     } else {
     624           0 :         Error=NaturalSpline(n,T,x,alphX,betX,MargCond,bx,cx,dx);
     625           0 :         if (Error!=0) return(Error+4);
     626           0 :         Error=NaturalSpline(n,T,y,alphY,betY,MargCond,by,cy,dy);
     627           0 :         if (Error!=0) return(Error+9);
     628             :     }
     629           3 :     return 0;
     630             : }
     631             : 
     632             : /*************************************************************************
     633             : |*
     634             : |*    CalcSpline()
     635             : |*
     636             : |*    Description       Calculates the coefficients of parametrised
     637             : |*                      natural or periodic cubic polynom-splines.
     638             : |*                      The corner points of the polygon passed are used
     639             : |*                      as support points. n returns the number of partial polynoms.
     640             : |*                      This function returns TRUE if no error occured.
     641             : |*                      Only in this case memory for the coefficient array
     642             : |*                      has been allocated, which can be freed by the caller
     643             : |*                      using a delete.
     644             : *************************************************************************/
     645             : 
     646           3 : bool CalcSpline(Polygon& rPoly, bool Periodic, sal_uInt16& n,
     647             :                 double*& ax, double*& ay, double*& bx, double*& by,
     648             :                 double*& cx, double*& cy, double*& dx, double*& dy, double*& T)
     649             : {
     650             :     sal_uInt8   Marg;
     651             :     double Marg01;
     652             :     double MargN1,MargN2;
     653             :     sal_uInt16 i;
     654           3 :     Point  P0(-32768,-32768);
     655           3 :     Point  Pt;
     656             : 
     657           3 :     n=rPoly.GetSize();
     658           3 :     ax=new double[rPoly.GetSize()+2];
     659           3 :     ay=new double[rPoly.GetSize()+2];
     660             : 
     661           3 :     n=0;
     662          42 :     for (i=0;i<rPoly.GetSize();i++) {
     663          39 :         Pt=rPoly.GetPoint(i);
     664          39 :         if (i==0 || Pt!=P0) {
     665          39 :             ax[n]=Pt.X();
     666          39 :             ay[n]=Pt.Y();
     667          39 :             n++;
     668          39 :             P0=Pt;
     669             :         }
     670             :     }
     671             : 
     672           3 :     if (Periodic) {
     673           3 :         Marg=3;
     674           3 :         ax[n]=ax[0];
     675           3 :         ay[n]=ay[0];
     676           3 :         n++;
     677             :     } else {
     678           0 :         Marg=2;
     679             :     }
     680             : 
     681           3 :     bx=new double[n+1];
     682           3 :     by=new double[n+1];
     683           3 :     cx=new double[n+1];
     684           3 :     cy=new double[n+1];
     685           3 :     dx=new double[n+1];
     686           3 :     dy=new double[n+1];
     687           3 :     T =new double[n+1];
     688             : 
     689           3 :     Marg01=0.0;
     690           3 :     MargN1=0.0;
     691           3 :     MargN2=0.0;
     692           3 :     if (n>0) n--; // correct n (number of partial polynoms)
     693             : 
     694           3 :     bool bRet = false;
     695           3 :     if ( ( Marg == 3 && n >= 3 ) || ( Marg == 2 && n >= 2 ) )
     696             :     {
     697           3 :         bRet = ParaSpline(n,ax,ay,Marg,Marg01,Marg01,MargN1,MargN2,false,T,bx,cx,dx,by,cy,dy) == 0;
     698             :     }
     699           3 :     if ( !bRet )
     700             :     {
     701           0 :         delete[] ax;
     702           0 :         delete[] ay;
     703           0 :         delete[] bx;
     704           0 :         delete[] by;
     705           0 :         delete[] cx;
     706           0 :         delete[] cy;
     707           0 :         delete[] dx;
     708           0 :         delete[] dy;
     709           0 :         delete[] T;
     710           0 :         n=0;
     711             :     }
     712           3 :     return bRet;
     713             : }
     714             : 
     715             : /*************************************************************************
     716             : |*
     717             : |*    Spline2Poly()
     718             : |*
     719             : |*    Description       converts a parametrised cubic spline (natural
     720             : |*                      or periodic) to an approximate polygon.
     721             : |*                      The function returns false, if an error occured
     722             : |*                      during the calculation of the coefficients or
     723             : |*                      the polygon became too large (>PolyMax=16380).
     724             : |*                      In the first case the polygon has 0, in the
     725             : |*                      second case PolyMax points.
     726             : |*                      To prevent coordinate overflows we limit
     727             : |*                      them to +/-32000.
     728             : |*
     729             : *************************************************************************/
     730           3 : bool Spline2Poly(Polygon& rSpln, bool Periodic, Polygon& rPoly)
     731             : {
     732           3 :     short  MinKoord=-32000;    // to prevent
     733           3 :     short  MaxKoord=32000;     // overflows
     734             : 
     735             :     double* ax;                // coefficients of the polynoms
     736             :     double* ay;
     737             :     double* bx;
     738             :     double* by;
     739             :     double* cx;
     740             :     double* cy;
     741             :     double* dx;
     742             :     double* dy;
     743             :     double* tv;
     744             : 
     745             :     double      Step;          // stepsize for t
     746             :     double      dt1,dt2,dt3;   // delta t, y, ^3
     747             :     double      t;
     748             :     bool        bEnde;         // partial polynom ended?
     749             :     sal_uInt16  n;             // number of partial polynoms to draw
     750             :     sal_uInt16  i;             // actual partial polynom
     751             :     bool        bOk;           // all still ok?
     752           3 :     sal_uInt16  PolyMax=16380; // max number of polygon points
     753             :     long        x,y;
     754             : 
     755           3 :     bOk=CalcSpline(rSpln,Periodic,n,ax,ay,bx,by,cx,cy,dx,dy,tv);
     756           3 :     if (bOk) {
     757           3 :         Step =10;
     758             : 
     759           3 :         rPoly.SetSize(1);
     760           3 :         rPoly.SetPoint(Point(short(ax[0]),short(ay[0])),0); // first point
     761           3 :         i=0;
     762          45 :         while (i<n) {       // draw n partial polynoms
     763          39 :             t=tv[i]+Step;
     764          39 :             bEnde=false;
     765       10714 :             while (!bEnde) {  // extrapolate one partial polynom
     766       10636 :                 bEnde=t>=tv[i+1];
     767       10636 :                 if (bEnde) t=tv[i+1];
     768       10636 :                 dt1=t-tv[i]; dt2=dt1*dt1; dt3=dt2*dt1;
     769       10636 :                 x=long(ax[i]+bx[i]*dt1+cx[i]*dt2+dx[i]*dt3);
     770       10636 :                 y=long(ay[i]+by[i]*dt1+cy[i]*dt2+dy[i]*dt3);
     771       10636 :                 if (x<MinKoord) x=MinKoord; if (x>MaxKoord) x=MaxKoord;
     772       10636 :                 if (y<MinKoord) y=MinKoord; if (y>MaxKoord) y=MaxKoord;
     773       10636 :                 if (rPoly.GetSize()<PolyMax) {
     774       10636 :                     rPoly.SetSize(rPoly.GetSize()+1);
     775       10636 :                     rPoly.SetPoint(Point(short(x),short(y)),rPoly.GetSize()-1);
     776             :                 } else {
     777           0 :                     bOk=false; // error: polygon becomes to large
     778             :                 }
     779       10636 :                 t=t+Step;
     780             :             } // end of partial polynom
     781          39 :             i++; // next partial polynom
     782             :         }
     783           3 :         delete[] ax;
     784           3 :         delete[] ay;
     785           3 :         delete[] bx;
     786           3 :         delete[] by;
     787           3 :         delete[] cx;
     788           3 :         delete[] cy;
     789           3 :         delete[] dx;
     790           3 :         delete[] dy;
     791           3 :         delete[] tv;
     792           3 :         return bOk;
     793             :     } // end of if (bOk)
     794           0 :     rPoly.SetSize(0);
     795           0 :     return false;
     796             : }
     797             : 
     798             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10