Interpolation: Cornu-Spiralen

Oft, sehr oft wurde ich nach Interpolationsverfahren gefragt. "Welches ist das beste Verfahren?" So oder ähnlich. Die bittere Wahrheit ist: Es gibt kein bestes Verfahren. Es gibt nur Verfahren, die für bestimmte Anwendungen weniger schlecht geeignet sind, als anderere. Und darüber hinaus kann man zu jedem Verfahren einen Datensatz konstruieren, der beliebig große Fehler erzeugt, wenn das Verfahren auf ihn angewendet wird. Also: Horizont überwinden und das richtige Verfahren wählen! Bis auf weiteres stelle ich hier nur eines vor: Die Cornu-Spiralen. Sie sind im Gegensatz zu Splines keine "Allerweltsinterpolation" und außerdem mathematisch ganz reizvoll.

Cornu-Spiralen

Alfred Cornu (6.3.1841-11.4.1902) ist der Namenspatron dieser Funktion. Cornu war Physiker und arbeitete auf dem Gebiet der Optik und Lichtausbreitung, Brechung und Strahlungsemission. Cornu ist aber nicht der Erfinder dieser Funktion! Sie werden erstmalig bei Jacob Bernoulli (Ca.1695) genannt, dann auch von Euler und Fresnel benutzt.

Cornu-Spiralen oder Klothoiden wurden laut Meek/Walton lange Jahre bei der Gestaltung von Autobahn-Verläufen eingesetzt. Früher wurden diese Kurven von Hand konstruiert, was ein mühsames Verfahren darstellt. Deshalb griff man häufig auf Schablonen zurück, was ebenfalls Zugeständnisse and die Einsatzmöglichkeiten erforderte. Erst der Computer öffnete das Feld. Der Übergang einer geraden Fahrbahn oder Gleises in einen Kreisbogen erfolgt aus naheliegenden Gründen nicht durch das direkte tangentiale Einmünden. In diesem Falle würde die auf das Fahrzeug wirkende Fliehkraft abrupt einsetzen. Nötig ist demnach die Verwendung einer Übergangskurve, die eine "gleichmäßige" Zunahme der Fliehkraft bewirkt. Im Eisenbahnbau wurden für diesen Zweck kubische Parabeln verwendet.

Cornu-Spiralen haben gegenüber anderen Verfahren, wie z.B. Bezier-Funktionen, den Vorteil, daß ihre Krümmung leicht vorgegeben bzw. errechnet werden kann. Demgegenüber ist ein etwas höherer Aufwand zu ihrer Berechnung nötig; ein heute glücklicherweise nicht mehr stichhaltiges Argument. Sowohl Cornu-Spiralen als auch Bezier-Funktionen haben im Gegensatz zu Splines die angenehme Eigenschaft, daß lokale Änderungen von Stützstellen nur zu lokalen Änderungen der konstruierten Kurve führen.

Ein paar Formeln

Wenn die alte Regel stimmt, daß eine Formel in einem Text 1000 Leute abschreckt, gehe ich jetzt ein kleines Risiko ein. Für die die keine Angst haben, verrate ich, daß diese Ausdrücke bei der späteren Anwendung auf einfache Art angenähert berechnet werden können.
Cornu-Spiralen werden in Parameterdarstellung von x und y wie folgt definiert:

xxx

wobei gilt

a Positiver Skalierungsfaktor

t nicht-negativer Laufparameter

xxx C(t)

xxx S(t)

Die Cornu-Spirale verläuft im ersten Quadranten. Sie beginnt mit t=0 im Ursprung des Koordinatensystems und nähert sich für t->xxx dem Punkt xxx

Mit C1 und S1 bezeichnen wir die Integrale der Fresnel-Integrale. Sie werden sich für die nächsten Betrachtungen noch als sehr nützlich erweisen.

xxx

xxx

Eine Anmerkung: Es finden sich verschiedene Möglichkeiten der Definition, die - abgesehen von Symmetrie und Darstellung - auf das Gleiche hinauslaufen. Für bestimmte Anwendungen ist die Verwendung von Komplexen Zahlen ganz praktisch; wir verzichten darauf.

 Anwendung: Gerade und Kreis

aaa

 Anwendung: Kleiner Kreis innerhalb eines größeren Kreises

aaa

 Anwendung: Ein Kreis oberhalb, einer unterhalb der x-Achse

aaa

 Anwendung: Zwei Kreise oberhalb der x-Achse

aaa

 Anwendung: Übergang zwischen zwei Geraden

aaa

 Praktische Umsetzung

1. Lösung der nichtlinearen Bestimmungsgleichung für A

Zur Lösung der Gleichung kann das Sekantenverfahren benutzt werden. Im Fall "Kleiner Kreis im großen Kreis" ist für manche Parameter nicht immer Konvergenz des Sekantenverfahrens zu erzielen. Insbesondere bei kleinen Abständen der Kreisbögen fand bei meinen Versuchen ein Überlauf bei der Berechnung statt. Hier heißt's also noch: selber forschen!

2. Berechnung der Fresnel-Integrale

Auch wenn die Formeln ein wenig abschrecken, man muß sich nicht die Mühe machen, die Fresnel-Integrale per numerischer Integration zu berechnen. Abramowitz/Stegun, aber auch Press und Heald geben gute Approximationsfunktionen an, die für praktische Zwecke vollkommen ausreichend sind. Eine Näherung über rationale Funktionen stellt dieser C-Code dar. Kopieren und benutzen - einfacher geht's nicht. Wie immer, ohne irgendwelche Rechtsansprüche. Jeder, der diesen Code verwendet, tut dies auf eigenes Risko.

                                       /* Koeffizienten fuer rationale      */
                                       /* Approximation:                    */
#define A0  1.0                        /* Die Koeffizienten mit Index 0     */
#define B0  2.0                        /* sind fuer alle Interpolations-    */
#define C0  1.0                        /* Funktionen gleich                 */
#define D0  1.4142135624               /* ...                               */
                                       /*-----------------------------------*/
                                       /* Maximaler Polynomgrad: 6          */
                                       /* max. Fehler: 4.0 E -8  (nach[1])  */
#define A51 0.1945161                  /* Koeffizienten fuer rationale      */
#define A52 0.2363641                  /* Funktion A_4_6                    */
#define A53 0.068324                   /* ...                               */
#define A54 0.0241212                  /* ...                               */
#define B51 2.9355041                  /* ...                               */
#define B52 2.7570246                  /* ...                               */
#define B53 1.875721                   /* ...                               */
#define B54 0.978113                   /* ...                               */
#define B55 0.356681                   /* ...                               */
#define B56 0.118247                   /* ...                               */
#define C51 0.7769507                  /* Koeffizienten fuer rationale      */
#define C52 0.6460117                  /* Funktion R_5_6                    */
#define C53 0.3460509                  /* ...                               */
#define C54 0.1339259                  /* ...                               */
#define C55 0.0433995                  /* ...                               */
#define D51 2.5129806                  /* ...                               */
#define D52 2.7196741                  /* ...                               */
#define D53 1.9840524                  /* ...                               */
#define D54 1.0917325                  /* ...                               */
#define D55 0.4205217                  /* ...                               */
#define D56 0.13634704                 /* ...                               */
                                       /*-----------------------------------*/
                                       /* Trigonometrische Konstanten       */
#define M_E     2.71828182845904523536 /* Eulersches e                      */
#define M_PI    3.14159265358979323846 /* Kreiszahl Pi                      */
#define M_PI_2  1.57079632679489661923 /* Pi /2                             */
#define E_DURCH_PI (M_E/M_PI)          /* e / Pi                            */

/*--------------------------------------------------------------------------*/
/* Prozedur zum Berechnen der Fresnel-Integrale                             */
/* C(x) und S(x) mit R_5_6 und A_4_6                                        */
/* Es ist vorteilhaft, diese Funktion zu benutzen, wenn sowohl C(x) als     */
/* auch S(x) benoetigt werden, weil dann der Rechenaufwand gegenueber den   */
/* Einzelaufrufen halbiert wird (Berechnung der rationalen Fkt. ist nur     */
/* einmal noetig)                                                           */
/*--------------------------------------------------------------------------*/
void n_fresnel_cs (                    /* Fresnel-Integrale C(x) und S(x)   */
   double x,                           /* Argument                          */
   double * c,                         /* Integral C(x) (Rueckkehrparameter)*/
   double * s )                        /* Integral S(x) (Rueckkehrparameter)*/
{                                      /* ...                               */
double a_4_6;                          /* Werte der rationalen Funktionen   */
double r_5_6;                          /* ... zur Interpolation             */
double xq;                             /* Puffer fuer x ^ 2                 */
a_4_6 = (A0 +                          /* Zaehlerpolynom                    */
         x * (A51 + x * (A52 + x * (A53 +  x *  A54)))) /
        (B0 +                          /* Nennerpolynom                     */
         x * (B51 + x * (B52 + x * (B53 + x * (B54 + x * (B55 + x *  B56))))));
                                       /*-----------------------------------*/
r_5_6 = (C0 +                          /* Zaehlerpolynom                    */
         x * (C51 + x * (C52 + x * (C53 + x * (C54 + x *  C55 ))))) /
        (D0 +                          /* Nennerpolynom                     */
         x * (D51 + x * (D52 + x * (D53 + x * (D54 + x * (D55 + x *  D56 ))))));
                                       /*-----------------------------------*/
xq = x * x;                            /* Quadrat von x berechnen           */
*s = 0.5 - r_5_6 *                     /* Fresnel-Integral annaehern        */
     cos(M_PI_2 * (a_4_6 - xq));       /* ...                               */
*c = 0.5 - r_5_6 *                     /* Fresnel-Integral annaehern        */
     sin(M_PI_2 * (a_4_6 - xq));       /* ...                               */
}                                      /* ENDE void n_fresnel_cs()          */


/*--------------------------------------------------------------------------*/
/* Funktion zum Berechnen des Fresnel-Integrals                             */
/* C(x) mit R_5_6 und A_4_6                                                 */
/*--------------------------------------------------------------------------*/
double n_fresnel_c (                   /* Fresnel-Integral C(x)             */
   double x )                          /* Argument                          */
{                                      /* ...                               */
double a_4_6;                          /* Werte der rationalen Funktionen   */
double r_5_6;                          /* ... zur Interpolation             */
a_4_6 = (A0 +                          /* Zaehlerpolynom                    */
         x * (A51 + x * (A52 + x * (A53 + x * (A54 ))))) /
        (B0 +                          /* Nennerpolynom                     */
         x * (B51 + x * (B52 + x * (B53 + x * (B54 + x * (B55 + x * (B56 )))))));
                                       /*-----------------------------------*/
r_5_6 = (C0 +                          /* Zaehlerpolynom                    */
         x * (C51 + x * (C52 + x * (C53 + x * (C54 + x * (C55 )))))) /
        (D0 +                          /* Nennerpolynom                     */
         x * (D51 + x * (D52 + x * (D53 + x * (D54 + x * (D55 + x * (D56 )))))));
return(0.5 - r_5_6 *                   /* Fresnel-Integral annaehern        */
       sin(M_PI_2 *                    /* ...                               */
       (a_4_6 - x * x)));              /* ...                               */
}                                      /* ENDE double n_fresnel_c           */


/*--------------------------------------------------------------------------*/
/* Funktion zum Berechnen des Integrals des Fresnel-Integrals               */
/* C1(x) mit R_5_6 und A_4_6                                                */
/*--------------------------------------------------------------------------*/
double n_fresnel_c1 (                  /* Fresnel-Integral C1(x)            */
   double x )                          /* Argument                          */
{                                      /* ...                               */
return(x * n_fresnel_c(x) -            /* Formel gemaess Aufsatz Meek/Walton*/
       E_DURCH_PI *                    /* ...                               */
       sin(M_PI_2 * x * x));           /* ...                               */
}                                      /* ENDE double n_fresnel_c1          */


/*--------------------------------------------------------------------------*/
/* Funktion zum Berechnen des Fresnel-Integrals                             */
/* S(x) mit R_5_6 und A_4_6                                                 */
/*--------------------------------------------------------------------------*/
double n_fresnel_s (                   /* Fresnel-Integral S(x)             */
   double x )                          /* Argument                          */
{                                      /* ...                               */
double a_4_6;                          /* Werte der rationalen Funktionen   */
double r_5_6;                          /* ... zur Interpolation             */
a_4_6 = (A0 +                          /* Zaehlerpolynom                    */
         x * (A51 + x * (A52 + x * (A53 + x * (A54 ))))) /
        (B0 +                          /* Nennerpolynom                     */
         x * (B51 + x * (B52 + x * (B53 + x * (B54 + x * (B55 + x * (B56 )))))));
                                       /*-----------------------------------*/
r_5_6 = (C0 +                          /* Zaehlerpolynom                    */
         x * (C51 + x * (C52 + x * (C53 + x * (C54 + x * (C55 )))))) /
        (D0 +                          /* Nennerpolynom                     */
         x * (D51 + x * (D52 + x * (D53 + x * (D54 + x * (D55 + x * (D56 )))))));
                                       /*-----------------------------------*/
return(0.5 - r_5_6 *                   /* Fresnel-Integral annaehern        */
       cos(M_PI_2 *                    /* ...                               */
       (a_4_6 - x * x)));              /* ...                               */
}                                      /* ENDE double n_fresnel_s           */


/*--------------------------------------------------------------------------*/
/* Funktion zum Berechnen des Integrals des Fresnel-Integrals               */
/* S1(x) mit R_5_6 und A_4_6                                                */
/*--------------------------------------------------------------------------*/
double n_fresnel_s1 (                  /* Fresnel-Integral S1(x)            */
   double x )                          /* Argument                          */
{                                      /* ...                               */
return(x * n_fresnel_s(x) +            /* Formel gemaess Aufsatz Meek/Walton*/
       E_DURCH_PI *                    /* ...                               */
       cos(M_PI_2 * x * x) -           /* ...                               */
       E_DURCH_PI);                    /* ...                               */
}                                      /* ENDE double n_fresnel_s1          */


Stand: 13.07.2003 /
 HPs Home      Mathematik/Home