Splines Verständnisfragen

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Splines Verständnisfragen

Beitrag von SMaag »

Vorab: ich weis was Splines sind, wozu man sie benötigt und hab eine Grundahnung von der Mathematik, die dahinter steht.

Ich hab aber als erstes mal Schwierigkeiten mit den Spline-Typen

B-Spline (Basis Spline) - Was ist das??
C-Spline (Cubic Spline) - ist das das gleiche wie Cubic Bezier??

Bezier-Spline/Curve in Cubic, Quadratic
allegemeine Bezier höher Ordung - wird anscheinend auch verwendet

Ich hab viel Code gesehen, der aber so verschachtelt ist, dass man nicht wirklich durchblickt und die Essenz davon rausbekommt.
Ich wusste, dass es sich bei einem Teil der Berechnungen um Vector-Produke bzw. Vector-Matrix Produkte zur Berechnung handeln muss!

Bei rosettacode.org, hab ich dann was gefunden, wo man das genau so sehen kann. Ich hab das als Brainstroming füür PB aufbereitet

Code: Alles auswählen

;SPLINE Brainstorming!!!

; https://rosettacode.org/wiki/Bitmap/B%C3%A9zier_curves/Cubic
; https://rosettacode.org/wiki/Bitmap/B%C3%A9zier_curves/Quadratic

EnableExplicit 

Structure TPoint2D
      X.d          
      Y.d          
EndStructure
 
Procedure _AllBernstein(n.i, u.d, Array AB.d(1))
  ; https://www.uni-ulm.de/fileadmin/website_uni_ulm/mawi.inst.070/ws15_16/AngewandteNumerik2/Vorlesungsskript/2015_08_19_AngNumerik2.pdf
  ; berechnet die AllBernstein Faktoren zu Gewichtung von B-Splines
  Protected.i I, K
  Protected.d u1, saved, temp 
  ReDim AB.d(n - 1)
  
  AB(0) = 1.0   
  u1 = 1 - u
  
  For I = 1 To n - 1

    saved = 0
    For K = 0 To I - 1
      temp = AB(K)
      AB(K) = saved + u1 * temp
      saved = u * temp
    Next
    AB(I) = saved
  Next
 EndProcedure

 Procedure.d _BinomialCoefficient(N.i, K.i)

  ; Binomialkoeffizient

  ; https://rosettacode.org/wiki/Evaluate_binomial_coefficients#Ada
  ; This is a port of the ADA Example because it uses a very effective 
  ; way to calcualte the result without calculating explicite N! K!
  
  ;                              N! 
  ;  BinomialCoefficient = -----------------
  ;                         ((N - K)! * K!) 
  
  Protected.i I, M
  Protected.d ret=1.0
 
  If N>K
    If K>=1     
      If K > N/2    ; Use symmetry
        M=N-K
      Else
        M=K
      EndIf     
      For I = 1 To M
        ret= ret * ((N-M+I)/I)  
      Next I     
    EndIf
  EndIf      
  ProcedureReturn ret
EndProcedure

Procedure Cubic_Bezier(Array PtOut.TPoint2D(1), *P1.TPoint2D, *P2.TPoint2D, *P3.TPoint2D, *P4.TPoint2D, Color.l=$FFFFFF, N = 20)
  
  Protected I
  Protected.d T, T1, A, B, C, D
  
  For I = 1 To N ;??? For I in Points'Range loop
     
    T =  I/N
    T1= 1.0 -T
    A = T1 *T1 * T1       ; A= (1.0-T)^3
    B = 3.0 * T * T1*T1   ; B= 3*T*(1-T)^2
    C = 3.0 * T*T * T1    ; C= 3*T^2 *(1-T)
    D = T*T*T             ; D= T^3     

    PtOut(I)\X =  A * *P1\X + B * *P2\X + C * *P3\X + D * *P4\X
    PtOut(I)\Y =  A * *P1\Y + B * *P2\Y + C * *P3\Y + D * *P4\Y   
  Next
   
  For I =1 To N-1   ; in Points'First..Points'Last - 1 loop
    LineXY(PtOut(I)\X, PtOut(I)\Y, PtOut(I+1)\X, PtOut(I+1)\Y, Color)
  Next
   
 EndProcedure
 
Procedure Quadratic_Bezier(Array PtOut.TPoint2D(1), *P1.TPoint2D, *P2.TPoint2D, *P3.TPoint2D, Color.l=$FFFFFF,  N = 20)
  
  Protected I
  Protected.d T, T1, A, B, C
  
  ReDim PtOut(N)
  
  For I = 1 To N ;??? For I in Points'Range loop
    T = I/N
    T1= 1.0 -T
    A = T1 * T1           ; A = (1-T)^2
    B = 2.0 * T * T1      ; B = 2 *T *(1.0 - T);
    C = T*T               ; T^2
   
    PtOut(I)\X = A * *P1\X + B * *P2\X + C * *P3\X 
    PtOut(I)\Y = A * *P1\Y + B * *P2\Y + C * *P3\Y    
  Next
  
  For I = 1 To N-1        ;  in Points'First..Points'Last - 1 loop
    LineXY(PtOut(I)\X, PtOut(I)\Y, PtOut(I+1)\X, PtOut(I+1)\Y, Color)
  Next
    
EndProcedure
Jetzt dazu noch ein paar Fragen zu den Prameterfunktion und Tabellen:

1. Die AllBernstein Faktoren zur Gewichtung der Splines
hier versteh ich schon nicht, was Gewichtung bedeuted!
Für welche Spline-Typen benötigt man das

2. Die BinomialCoefficient aus den Fakultäten, soweit noch klar was das ist.
für welche Splines benötigt man das?

Mein Problem ist, dass ich von diesen Parametern im Code für die Cubic und Qudaratic Bezier nicht erkennen kann!

3. Cubic Spline Interpolation wird duch 4 Punkte bestimmt, Quadratic durch 3
wenn der Spline mehr Punkte hat, wo muss ich dann bei der Interolation des 2ten Segment ansetzen?
- beim 2ten Punkt?
- beim letzten Punkt des vorherigen Segments?
- beim Folgepunkt nach dem 1 Segment?

Kann mir da jemand etwas Licht ins Dunkel bringen?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8677
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Splines Verständnisfragen

Beitrag von NicTheQuick »

Ich bin in dem Thema nicht so drin um dir das genau erklären zu können. Aber ich habe gerade das hier gefunden, was dir vielleicht auf die Sprüngen helfen könnte: https://www.youtube.com/watch?v=jZPCGVssyiw
Hier ist Teil 2: https://www.youtube.com/watch?v=7UtZpzbjC7Y
Teil 3 und 4 fehlen aber scheinbar?
Da geht es auch um die Bernsteinpolynome und im zweiten Teil darum wie man das ganze mit beliebig vielen Kontrollpunkten machen kann.
Bild
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Re: Splines Verständnisfragen

Beitrag von SMaag »

Danke, aber das bringt mich nicht weiter, das kenn ich schon und das Prinzip ist mir auch klar.

hier nochmal ein anders Codebeispiel für Bezier, dass ich glaub von Pascal auf PB konvertiert habe, weil es eben auch relativ
einfach aussieht.
Es ist auch Bezier_C, das ist aber was kompett anderes als mein erstes Beispiel.
Hier werden Polynome höherer Ordnung (in Anazhl der Punkte x^n) verwendet und über alle Punkte summiert.
Das ist definitiv was anders als mit den 4 Punkten und 4 Parametern vom ersten Beispiel.
Angeblich soll das, dass klassische Bernstein Polynom sein. Die Berechnung der Faktoren im Beispiel hat aber
irgendwie nix mit der Berechnung der AllBernstein Gewichtsfaktoren gemein!???

Code: Alles auswählen

Procedure.d _FactorDbl(N2.i, N1.i=2)   
; berechnet fortlaufendes Produkt aus ganzen Zahlen von N1..N2
; bzw. Fakultät N! wenn N1=2!       
 Protected.i ret
   
  If N1 > 1
    ret = 1.0
    While N2>=N1    
      ret * N2
      N2 - 1
    Wend
  EndIf  
  ProcedureReturn ret
EndProcedure
 
Procedure Bezier_C(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Berechnet die Bunkte der Bezier Kurve mit Parameter 
  ;   (0 <= u <= 1). Die Kurve wird parametrisch berechnet 
  ;   mit 0=0 für den ersten Punkt und u=1 für den letzten 
  ;   Punkt!
  ;   Dieser Algorithmus ist die klassische Form des Bernstein Polynoms
   
   Protected.i I, K, nPIn, nPOut, NF
    Protected.d u, BF
    
    nPIn = ArraySize(PtIn())      ; N Points-In
    nPOut = ArraySize(PtOut())    ; n Points-Out
   
    For I = 0 To nPOut
      u = (I) / (nPOut)
      PtOut(I)\X = 0.0
      PtOut(I)\Y = 0.0
      ;PtOut(I)\Z = 0.0       ; for 3D Splines
      
      For K = 0 To nPIn
          BF = _FactorDbl(nPIn, K+1) * Pow(u, K) * Pow((1.0-u), (nPIn-K)) / _Factor(nPIn-K)
        
        PtOut(I)\X = PtOut(I)\X + PtIn(K)\X * BF
        PtOut(I)\Y = PtOut(I)\Y + PtIn(K)\Y * BF
        ;PtOut(I)\Z = PtOut(I)\Z + PtIn(K)\Z * BF  ; for 3D Splines
      Next K
    Next I
  
EndProcedure

Ich suche nach der "Essenz"
was macht den B-Spline zum B-Spline und den C-Spline zum C-Spine ...
B-/C- Splines unterscheiden sich von Bezierkuren, so weit bin ich mittlerweile schon.

ich glaub:
C-Spline liegt liegt ausserhalb des aufgespannten Radius der Linienverbindungen der Punkte
B-Spline innerhalb des Radius
und Bezier schmiegt sich je nach Ploynom-Ordung und Parameterauswahl am besten an die Linie an.

Irgendwie hab ich gefühlt alle Infos zusammen. Es fehlt aber noch der Klick im Kopf wie das alles Zusammenhängt.
Ne einfache Beischreibung, die sich auf die nötigen Basics für Anwender beschränkt hab ich leider nicht gefunden.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8677
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Splines Verständnisfragen

Beitrag von NicTheQuick »

Wenn du das Video schon gesehen hast, dann weiß ich nicht genau wo das Verständnisproblem liegt.

Du kannst Bézier Curves aus beliebig vielen Kontrollpunkten bauen. Die Änderung eines einzigen Kontrollpunktes ändert aber auch die komplette Kurve. Je nachdem wie viele Kontrollpunkte sie haben, desto höher ist auch der Grad ihres zugrunde liegenden Polynoms. Die Binominalkoeffizienten kannst du nutzen um das expandierte Polynom zu berechnen. Hast du einen Kontrollpunkt, hast du eine quadratische Bézier Curve, hast du zwei, dann ist es eine kubische Bézier Curve.

Packst du jetzt mehrere Bézier-Kurven eines festen Grades hintereinander, dann entsteht ein B-Spline.

Bei meiner Recherche gerade eben sind mir dann auch noch C-Splines, M-Splines, I-Splines, Natural cubic Splines und Bernstein Polynome über den Weg gelaufen (siehe Introduction to splines2. Wie die alle miteinander verbunden sind oder ob das alles komplett unabhängige Dinge sind, kann ich dir jetzt leider auch nicht sagen. C-Splines scheinen jedenfalls die Eigenschaft zu haben, dass sie immer konvex sind, deswegen wohl auch C für convex. Das sind skalierte Integrale der I-Splines, die wiederum die integrierte Version der M-Splines darzustellen scheinen.

Aber ich glaube da hört mein Verständnis auch so langsam auf. Uni Mathe ist zu lange her. :-D
Bild
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Re: Splines Verständnisfragen

Beitrag von SMaag »

Packst du jetzt mehrere Bézier-Kurven eines festen Grades hintereinander, dann entsteht ein B-Spline.
Ich glaub jetzt hat's geklickt! Ich fasse das nochmal zusammen, wie ich das mittlerweile verstanden habe.

Quadatic Bezier: Eine durch 3 Punkte bestimme Kurve
Cubic Bezier : eine durch 4 Punkte bestimmte Kurve
Rational Bezier: die Kurve verläuft durch 5 oder mehr Punkte - Polynomgrad durch Anzahl der Punkte bestimmt.

mehrere Segemente z.B. 3 Cubic Bezier mit je 4 Punkten hintereinader => Bezier-Spline (B-Spline)

Bis zum Cubic Bezier mit 4 Punkten macht es gar keinen Sinn, die Polynomfaktoren zu berechnen,
das kann man schnell mit Hand eintragen und fix die 4 Faktoren A, B, C, D angeben.
Bei höheren Ordnungen per Funktion berechnen!

Mein Fehler war die Vorstellung von Vektormultiplikationen.
Bei 3 und 4 Punkten sind das 3 bzw. 4-Dimensionale Vektoren. Bei 5 Punkten eben 5-Dimensionale
(ich hatte die Vorstellung das bleibt auch bei mehren Punkten eine max. 4-dimensioanle Vektor-Multiplikation wegen des 3D-Raumes
das ist aber Quatsch!)


Bleibt noch eine grundlegende Frage:
Ich hab mehere Codes gesehen, die mit einer 4x4 Koeffizientenmatrix arbeiten.
nennt sich mal Spline, mal C-Spline.
einer davon auch im englischen Forum:
https://www.purebasic.fr/english/viewtopic.php?p=465279

Ist das nun das gleiche wie Cubic Bezier nur anders dargestellt oder ist das nochmal was anderes???

hier mal Matrix Beispiele! Sieht auch jedes mal anders aus!

Code: Alles auswählen

; Version A
; ---------------------------------------
Coeffs(0,0) = 2
Coeffs(0,1) = -2
Coeffs(0,2) = 1
Coeffs(0,3) = 1

Coeffs(1,0) = -3
Coeffs(1,1) = 3
Coeffs(1,2) = -2
Coeffs(1,3) = -1

Coeffs(2,0) = 0
Coeffs(2,1) = 0
Coeffs(2,2) = 1
Coeffs(2,3) = 0

Coeffs(3,0) = 1
Coeffs(3,1) = 0
Coeffs(3,2) = 0

; Version B
; ---------------------------------------
s(1)\X = 0.0
s(NPI)\X = 0.0
s(1)\Y = 0.0
s(NPI)\Y = 0.0
For I = 1 To NPI-1
  cof(4, I)\X = (s(I+1)\X - s(I)\X) / 6.0 / H
  cof(4, I)\Y = (s(I+1)\Y - s(I)\Y) / 6.0 / H
  cof(3, I)\X = s(I)\X / 2.0
  cof(3, I)\Y = s(I)\Y / 2.0
  cof(2, I)\X = (PtIn(I)\X - PtIn(I-1)\X) / H - (2.0 * s(I)\X + s(I+1)\X) * H / 6.0
  cof(2, I)\Y = (PtIn(I)\Y - PtIn(I-1)\Y) / H - (2.0 * s(I)\Y + s(I+1)\Y) * H / 6.0
  cof(1, I)\X = PtIn(I-1)\X
  cof(1, I)\Y = PtIn(I-1)\Y
Next I
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Re: Splines Verständnisfragen

Beitrag von SMaag »

Ich denk jetzt hat sich das erledigt
hab das hier gefunden, was praktisch alles beantwortet:

Part 1 Cubic Curves : https://www.youtube.com/watch?v=YMl25iCCRew
Part 2 come together : https://www.youtube.com/watch?v=DLsqkWV6Cag
Part 3 2D and B-Splines : https://www.youtube.com/watch?v=JwN43QAlF50
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Re: Splines Verständnisfragen

Beitrag von SMaag »

Das hab ich nun über Splines rausgefunden

; ----------------------------------------------------------------------
; 1. Natural Cubic Curve
; ----------------------------------------------------------------------
; Biegekurve, minimiert die Biegenergie!
; at³ + bt² +ct +d
; 4 Kontrollpunkte oder 2 Kontrollpunkte und 2 Krümmungen (Tensions)

; ----------------------------------------------------------------------
; 2. Catmull-Rom Spline
; ----------------------------------------------------------------------
;
; C1 Kontinuität = Kontinuität in der 1 Ableitung (Steigung)
;
; Folge von Punkten, die im Übergang stetig sind d.h. gleiche Steigung
; es bleibt als Freiheitsgrad am Übergang Krümmung (Tension) dadurch
; sind korrekte Übergänge mit unterschiedlichen Steigungen möglich.
; Es wird die eine Mittlere Steigung verwendet, bestimmt aus der
; Geraden vom Punkt 1 zu Punkt 3.
; die so erzeugte Folge nennt man dan Catumull-Rom-Spline

; ----------------------------------------------------------------------
; 2. Natural Cubic Spline
; ----------------------------------------------------------------------
;
; C2 Kontinuität = Kontinuität in der 2 Ableitung (Krümmung)
;
; Folge von Punkten, die im Übergang stetig sowohl in Steigung als
; auch Krümmung sind (identische Steigung und Krümmung)
; Kein Freiheitsgrad mehr im Übergang (es gibt nur eine Lösung)
; (minimierte Biegeenergie!)

; ----------------------------------------------------------------------
; 2. Bezier Splines
; ----------------------------------------------------------------------

; C2 Kontinuität : Kontinuität in der 2 Ableitung (Krümmung)
; Ableitung einer Bezier-Kurve ist wieder eine Bezier-Kurve mit um
; 1 nierigerer Ordnung

; ----------------------------------------------------------------------
; Eigenschaften Tabelle Splines
; ----------------------------------------------------------------------
; Catmull-Rom ... C1 + interpolierend + local control
; Natural-Cubic... C1 + C2 + interpolierend
; Bezier............ C2 + C2 + local control
; ----------------------------------------------------------------------

; C1: Kontinuität in der 1. Ableitung (Steigung) s1=s2, k1<>k2
; C2: Kontinuität in der 2. Ableitung (Krümmung) s1=s2, k1 =k2

; local Control: Bei Änderung eines Kontrollpunktes wirkt sich das nur
; local aus. Also zwischen den beiden benachbarten Punkten.
; Bei den anderen Splines wirkt sich das weiter entfernt noch aus!
Benutzeravatar
alter Mann
Beiträge: 201
Registriert: 29.08.2008 09:13
Wohnort: hinterm Mond

Re: Splines Verständnisfragen

Beitrag von alter Mann »

Noch ein paar (ungeordnete) Bemerkungen:
1. alle genannten Splinetypen lassen sich ineinander umrechnen.
2. bei rationalen (B-)Splines haben alle Kontrollpunkte ein "Gewicht" - je höher das Gewicht, desto näher wird die "Kurve" an den Kontrollpunkt "gezogen"
3. mit rationalen Splines lassen sich Kreise, Ellipsen, Hyperbeln exakt beschreiben
4. es gibt eine Vielzahl weiterer Splinetypen (Akima,Renner,Hermite... letzter wird z.B. durch Polynome vom Grad 5 beschrieben)
5. eine gute Literaturquelle: "Grundlagen der geometrischen Datenverarbeitung" von Hosckek/Lasser
6. mit Splines lassen sich auch Flächen / Räume usw. darstellen (wobei letzteres nicht so verbreitet ist)
Win11 64Bit / PB 6.0
DarkDragon
Beiträge: 6267
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: Splines Verständnisfragen

Beitrag von DarkDragon »

Also, B-Splines sind mit Bézier Kurven verwandt und man kann die Verwandtschaft gut in ihrer Polarform sehen wenn ich mich nicht täusche, aber sie sind eine eigenständige Art. Was bei der Bézier Kurve der de Casteljau Algorithmus ist, ist bei den B-Splines der de Boor Algorithmus. C-Splines habe ich bisher noch nicht gehört, kann mir aber Catmull-Rom Splines darunter vorstellen. Diese sind lediglich Hermite Segmente, die zusammengesteckt werden und Hermite Segmente interpolieren analog zur Lagrange Interpolation auch die Ableitungen.

Es sind weniger Vektoren und Matrizen als man denkt, es geht viel mehr um affine Kombinationen. D.h. man hat Funktionen der Form

p(t) = Summe von i = 0 bis n aus a_i * x(t)

Wobei x(t) dann die Basis bildet. Das ist sowohl bei Lagrange Interpolation, Newton Interpolation, Hermite Interpolation und Catmull-Rom Splines so. Es gibt verschiedene Parametrisierungsansätze, um dann letztendlich vom Funktionsraum in den Vektorraum zu kommen: äquidistante Parametrisierung, Chordal nach der Kurvenlänge, Zentripetal nach dem Moment, Foley-Parametrisierung, ... .

Bei Bézier Kurven bilden die Bernstein Polynome die Basis. Bernstein Polynome besitzen die Eigenschaft, dass sie affin invariant sind, d.h. ob du zuerst eine affine Abbildung ausführst und dann das polynom auswertest oder umgekehrt spielt keine Rolle. Außerdem summieren Sie sich auf 1 auf, was aus dem ganzen wiederum eine affine (und nicht nur lineare) Kombination macht. Eine Bézier Kurve vom Grad n hat n + 1 Kontrollpunkte und nur die Endpunkte werden zwingend interpoliert, der Rest der Kurve liegt irgendwo in der konvexen Hülle aller Kontrollpunkte. Aber d.h. auch, dass ein neu hinzugefügter Stützpunkt Einfluss auf alle Bereiche der Kurve hat (sieht man ja schon am de Casteljau Algorithmus).

Bernstein Polynome sehen so aus:

B_i^n(t) = (n over i) * (1 - t)^{n-i} t^i

und sie haben auch eine rekursive Definition:

B_i^{n+1}(t) = t B_{i-1}^n(t)
+ (1 - t) B_i^n(t)
B_{-1}^n = B_{n+1}^n = 0
B_0^0 = 1

Im Prinzip findet das in _AllBernstein statt, man berechnet eine Dreiecksmatrix von Bernstein-Werten, deshalb die äußere for Schleife bis n und die innere nur bis zum Zähler der äußeren.

B-Splines gehen mal einen etwas anderen Weg. B-Splines vom Grad n sind zusammengesetzt aus C^{n-1} (bis zur n-1ten Ableitung) stetigen Segmenten vom Grad n und es wird durch Knotenpunkte interpoliert mit geeigneten Übergangsbedingungen. Ihre Basis lautet wie folgt:

N_{i, 0}(t) = 1 für t_i ≤ t < t_{i+1} und 0 sonst
N_{i, n}(t) = ((t - t_i) / (t_{n+i} - t_i)) * N_{i, n-1}(t) + ((t_{n+i+1} - t) / (t_{n+i+1} - t_{i+1})) * N_{i, n-1}(t)

Die Bernstein Polynome B_i^n vom Grad n sind ein Spezialfall der B-Splines N_{i, n} vom Grad n mit zwei Knoten der Vielfachheit n, d.h. der Knotenvektor ist (0, 0, 0, ..., 1, 1, 1) Beweis. Man unterscheidet außerdem zwischen Knoten im Parameterraum und Knoten im Vektorraum. Wir haben sie damals Knots und Nodes genannt, im deutschen wirds glaub etwas schwieriger.

---

Rationale B-Splines sind einfach nur B-Splines, die mit rationalen Zahlen (Brüche ganzer Zahlen) berechnet werden, damit genug Präzision erreicht wird und keine numerischen Ungenauigkeiten drin sind. Kein Autobauer will Stufen auf der Motorhaube eingefräst sehen und die Lücken sollten möglichst gleichmäßig und möglichst gering sein. Folglich wird auf non-uniform rational B-Spline surfaces (kurz NURBS) beim Autobau gesetzt. Paul de Faget de Casteljau arbeitete bei Citroën und Renault.

Ich hoffe ich konnte damit helfen.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
SMaag
Beiträge: 152
Registriert: 08.05.2022 12:58

Spline Code in VB

Beitrag von SMaag »

Jetzt hab ich eine wohl ziemlich vollständige Implementierung verschiedener Splines in VB
gefunden. Vorlage für den Code von flanguasco, waren Fortran implementierungen.

Wenn jemand Lust hat, Teile davon zu übersetzen. Ich kann dafür jede Hilfe gut gebrauchen.
das komplette Spline Projekt kann man downloaden unter:
http://www.flanguasco.org/VisualBasic/VisualBasic.html

Code: Alles auswählen

Attribute VB_Name = "modSplines"
'==============================================================
' Descrizione.....: Routines di interpolazione con Splines.
' Nome dei Files..: Splines_01.bas
' Data............: 27/11/1999
' Aggiornamento...: 18/7/2002 (migliorata la Bezier).
' Versione........: 1.0 a 32 bits
' Sistema.........: Visual Basic 6.0 sotto Windows NT.
' Scritto da......: F. Languasco ®
' E-Mail..........: MC7061@mclink.it
' DownLoads a.....: http://members.xoom.virgilio.it/flanguasco/
'                   http://www.flanguasco.org
'==============================================================
'
'   Gli algoritmi usati sono di:
'   P. Bourke     -  Aprile 1989
'   D. Cholaseuk  -  8/Dic./1999
'
'   Le curve Splines vengono calcolate in modo parametrico
'   e quindi, con opportuni adattamenti, possono essere
'   usate per interpolare punti a n dimensioni.
'
Option Explicit
'
Public Type P_Type
    X As Double         ' Coordinate x dei punti.
    Y As Double         ' Coordinate y dei punti.
    'z As Double         ' Coordinate z dei punti.
End Type
Public Sub Bezier_C(Pi() As P_Type, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva di Bezier calcolata
'   al valore u (0 <= u <= 1). La curva e' calcolata in modo
'   parametrico con il valore 0 di u corrispondente a Pc(0)
'   ed il valore 1 corrispondente a Pc(NPC_1).
'   Questo algoritmo ricalca la forma classica del polinomio
'   di Bernstein.
'
   Dim I&, K&, NPI_1&, NPC_1&, NF&, u#, BF#
'
    NPI_1 = UBound(Pi)
    NPC_1 = UBound(Pc)
    'NF = Prodotto(NPI_1)
'
    For I = 0 To NPC_1
        u = CDbl(I) / CDbl(NPC_1)
        Pc(I).X = 0#
        Pc(I).Y = 0#
        'Pc(I).z = 0#
        For K = 0 To NPI_1
            'BF = NF * (u ^ K) * ((1 - u) ^ (NPI_1 - K)) _
                / (Prodotto(K) * Prodotto(NPI_1 - K))
            BF = Prodotto(NPI_1, K + 1) * (u ^ K) * ((1# - u) ^ (NPI_1 - K)) _
               / Prodotto(NPI_1 - K)
            Pc(I).X = Pc(I).X + Pi(K).X * BF
            Pc(I).Y = Pc(I).Y + Pi(K).Y * BF
            'Pc(I).z = Pc(I).z + Pi(K).z * BF
        Next K
    Next I
'
'
'
End Sub
Public Sub Bezier_1(Pi() As P_Type, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva di Bezier.
'   La curva e' calcolata in modo parametrico (0 <= u < 1)
'   con il valore 0 di u corrispondente a Pc(0);
'   Attenzione: il punto Pc(NPC_1), corrispondente al valore u = 1,
'               non puo' essere calcolato.
'
'   Parametri:
'       Pi(0 to NPI - 1):   Vettore dei punti, dati, da
'                           approssimare.
'       Pc(0 to NPC - 1):   Vettore dei punti, calcolati,
'                           della curva approssimante.
'
   Dim I&, K&, NPI_1&, NPC_1&
   Dim u#, u_1#, ue#, u_1e#, BF#
'
    NPI_1 = UBound(Pi) ' N. di punti da approssimare - 1.
    NPC_1 = UBound(Pc) ' N. di punti sulla curva - 1.
'
    ' La curva inizia sempre da Pi(0) -> u = 0:
    Pc(0).X = Pi(0).X
    Pc(0).Y = Pi(0).Y
    'Pc(0).z = Pi(0).z
'
    For I = 1 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        ue = 1#
        u_1 = 1# - u
        u_1e = u_1 ^ NPI_1
'
        Pc(I).X = 0#
        Pc(I).Y = 0#
        'Pc(I).z = 0#
        For K = 0 To NPI_1
            BF = Prodotto(NPI_1, K + 1) * ue * u_1e / Prodotto(NPI_1 - K)
            Pc(I).X = Pc(I).X + Pi(K).X * BF
            Pc(I).Y = Pc(I).Y + Pi(K).Y * BF
            'Pc(I).z = Pc(I).z + Pi(K).z * BF
'
            ue = ue * u
            u_1e = u_1e / u_1
        Next K
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
    'Pc(NPC_1).z = Pi(NPI_1).z
'
'
'
End Sub
Public Sub Bezier(Pi() As P_Type, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva di Bezier.
'   La curva e' calcolata in modo parametrico (0 <= u < 1)
'   con il valore 0 di u corrispondente a Pc(0);
'
'   Questa versione elimina alcuni problemi di "underflow"
'   e di "overflow" presentati dalla Bezier_1 e dalla Bezier_C.
'
'   Parametri:
'       Pi(0 to NPI - 1):   Vettore dei punti, dati, da
'                           approssimare.
'       Pc(0 to NPC - 1):   Vettore dei punti, calcolati,
'                           della curva approssimante.
'
   Dim I&, K&, NPI_1&, NPC_1&
   Dim u#, u_1#, ue#, BF#
   Static NPI_1_O&, CB_Tav#()
'
    NPI_1 = UBound(Pi) ' N. di punti da approssimare - 1 (deve essere 2 <= NPI_1 <= 1029).
    NPC_1 = UBound(Pc) ' N. di punti sulla curva - 1.
'
    If NPI_1_O <> NPI_1 Then
        ' Prepara la tavola dei coefficienti binomiali:
        ReDim CB_Tav#(0 To NPI_1)
        For K = 0 To NPI_1
            CB_Tav(K) = rncr(NPI_1, K)
        Next K
'
        NPI_1_O = NPI_1
    End If
'
    ' La curva inizia sempre da Pi(0) -> u = 0:
    Pc(0).X = Pi(0).X
    Pc(0).Y = Pi(0).Y
    'Pc(0).z = Pi(0).z
'
    For I = 1 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        ue = 1#
        u_1 = 1# - u
'
        Pc(I).X = 0#
        Pc(I).Y = 0#
        'Pc(I).z = 0#
        For K = 0 To NPI_1
            BF = CB_Tav(K) * ue * u_1 ^ (NPI_1 - K)
'
            Pc(I).X = Pc(I).X + Pi(K).X * BF
            Pc(I).Y = Pc(I).Y + Pi(K).Y * BF
            'Pc(I).z = Pc(I).z + Pi(K).z * BF
'
            ue = ue * u
        Next K
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
    'Pc(NPC_1).z = Pi(NPI_1).z
'
'
'
End Sub
Public Sub Bezier_P(Pi() As P_Type, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva di Bezier calcolata
'   al valore u (0 <= u < 1). La curva e' calcolata in modo
'   parametrico con il valore 0 di u corrispondente a Pc(0);
'   Attenzione: il punto Pc(NPC_1), corrispondente al valore u = 1,
'               non puo' essere calcolato.
'
'   Questo algoritmo (tratto da una pubblicazione di P. Bourke
'   e tradotto dal C) e' particolarmente interessante, in quanto
'   evita l' uso dei fattoriali della forma normale.
'
    Dim K&, I&, KN&, NPI_1&, NPC_1&, NN&, NKN&
    Dim u#, uk#, unk#, Blend#
'
    NPI_1 = UBound(Pi)
    NPC_1 = UBound(Pc)
'
    For I = 0 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        uk = 1#
        unk = (1# - u) ^ NPI_1
'
        Pc(I).X = 0#
        Pc(I).Y = 0#
        'Pc(I).z = 0#
'
        For K = 0 To NPI_1
            NN = NPI_1
            KN = K
            NKN = NPI_1 - K
            Blend = uk * unk
            uk = uk * u
            unk = unk / (1# - u)
            Do While NN >= 1
                Blend = Blend * CDbl(NN)
                NN = NN - 1
                If KN > 1 Then
                    Blend = Blend / CDbl(KN)
                    KN = KN - 1
                End If
                If NKN > 1 Then
                    Blend = Blend / CDbl(NKN)
                    NKN = NKN - 1
                End If
            Loop
'
            Pc(I).X = Pc(I).X + Pi(K).X * Blend
            Pc(I).Y = Pc(I).Y + Pi(K).Y * Blend
            'Pc(I).z = Pc(I).z + Pi(K).z * Blend
        Next K
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
    'Pc(NPC_1).z = Pi(NPI_1).z
'
'
'
End Sub
Private Function Prodotto(ByVal N2&, Optional ByVal N1& = 2) As Double
'
'   Ritorna il prodotto dei numeri, consecutivi, interi e positivi,
'   da N1 a N2 (0 < N1 <= N2). Se N1 > N2 ritorna 1.
'   Se N1 manca, ritorna il Fattoriale di N2; in questo caso puo'
'   anche essere N2 = 0 perche', per definizione, e' 0! = 1:
'
    Dim Pr#, I&
'
    Pr = 1#
    For I = N1 To N2
        Pr = Pr * CDbl(I)
    Next I
'
    Prodotto = Pr
'
'
'
End Function
Public Sub B_Spline(Pi() As P_Type, ByVal NK&, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva B-Spline.
'   La curva e' calcolata in modo parametrico (0 <= u <= 1)
'   con il valore 0 di u corrispondente a Pc(0) ed il valore
'   1 corrispondente a Pc(NPC_1).
'
'   Parametri:
'       Pi(0 to NPI - 1):   Vettore dei punti, dati, da
'                           approssimare.
'       Pc(0 to NPC - 1):   Vettore dei punti, calcolati,
'                           della curva approssimante.
'       NK:                 Numero di nodi della curva
'                           approssimante:
'                           NK = 2    -> segmenti di retta.
'                           NK = 3    -> curve quadratiche.
'                           ..   .       ..................
'                           NK = NPI  -> splines di Bezier.

    Dim NPI_1&, NPC_1&, I&, J&, tmax#, u#, ut#, bn#()
    Const Eps = 0.0000001
'
    NPI_1 = UBound(Pi)  ' N. di punti da approssimare - 1.
    NPC_1 = UBound(Pc)  ' N. di punti sulla curva - 1.
    tmax = NPI_1 - NK + 2
'
    ' La curva inizia sempre da Pi(0) -> u = 0:
    Pc(0).X = Pi(0).X
    Pc(0).Y = Pi(0).Y
'
    For I = 1 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        ut = u * tmax
        If Abs(ut - CDbl(NPI_1 + NK - 2)) <= Eps Then
            Pc(I).X = Pi(NPI_1).X
            Pc(I).Y = Pi(NPI_1).Y
        Else
            Call B_Basis(NPI_1, ut, NK, bn())
            Pc(I).X = 0#
            Pc(I).Y = 0#
            For J = 0 To NPI_1
                Pc(I).X = Pc(I).X + bn(J) * Pi(J).X
                Pc(I).Y = Pc(I).Y + bn(J) * Pi(J).Y
            Next J
        End If
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
'
'
'
End Sub
Private Sub B_Basis(ByVal NPI_1&, ByVal ut#, ByVal K&, bn#())
'
'   Compute the basis function (also called weight)
'   for the B-Spline approximation curve:
'
    Dim NT&, I&, J&
    Dim b0#, b1#, bl0#, bl1#, bu0#, bu1#
    ReDim bn#(0 To NPI_1 + 1), bn0#(0 To NPI_1 + 1), t#(0 To NPI_1 + K + 1)
'
    NT = NPI_1 + K + 1
    For I = 0 To NT
        If (I < K) Then t(I) = 0#
        If ((I >= K) And (I <= NPI_1)) Then t(I) = CDbl(I - K + 1)
        If (I > NPI_1) Then t(I) = CDbl(NPI_1 - K + 2)
    Next I
    For I = 0 To NPI_1
        bn0(I) = 0#
        If ((ut >= t(I)) And (ut < t(I + 1))) Then bn0(I) = 1#
        If ((t(I) = 0#) And (t(I + 1) = 0#)) Then bn0(I) = 0#
    Next I
'
    For J = 2 To K
        For I = 0 To NPI_1
            bu0 = (ut - t(I)) * bn0(I)
            bl0 = t(I + J - 1) - t(I)
            If (bl0 = 0#) Then
                b0 = 0#
            Else
                b0 = bu0 / bl0
            End If
            bu1 = (t(I + J) - ut) * bn0(I + 1)
            bl1 = t(I + J) - t(I + 1)
            If (bl1 = 0#) Then
                b1 = 0#
            Else
                b1 = bu1 / bl1
            End If
            bn(I) = b0 + b1
        Next I
        For I = 0 To NPI_1
            bn0(I) = bn(I)
        Next I
    Next J
'
'
'
End Sub
Public Sub C_Spline(Pi() As P_Type, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva C-Spline.
'   La curva e' calcolata in modo parametrico (0 <= u <= 1)
'   con il valore 0 di u corrispondente a Pc(0) ed il valore
'   1 corrispondente a Pc(NPC_1).
'
'   Parametri:
'       Pi(0 to NPI - 1):   Vettore dei punti, dati, da
'                           interpolare.
'       Pc(0 to NPC - 1):   Vettore dei punti, calcolati,
'                           della curva interpolante.
'
    Dim NPI_1&, NPC_1&, I&, J&
    Dim u#, ui#, uui#
    Dim cof() As P_Type
'
    NPI_1 = UBound(Pi)      ' N. di punti da interpolare - 1.
    NPC_1 = UBound(Pc)      ' N. di punti sulla curva - 1.
'
    Call Find_CCof(Pi(), NPI_1 + 1, cof())
'
    ' La curva inizia sempre da Pi(0) -> u = 0:
    Pc(0).X = Pi(0).X
    Pc(0).Y = Pi(0).Y
'
    For I = 1 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        J = Int(u * CDbl(NPI_1)) + 1
        If (J > (NPI_1)) Then J = NPI_1
'
        ui = CDbl(J - 1) / CDbl(NPI_1)
        uui = u - ui
'
        Pc(I).X = cof(4, J).X * uui ^ 3 + cof(3, J).X * uui ^ 2 + cof(2, J).X * uui + cof(1, J).X
        Pc(I).Y = cof(4, J).Y * uui ^ 3 + cof(3, J).Y * uui ^ 2 + cof(2, J).Y * uui + cof(1, J).Y
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
'
'
'
End Sub
Private Function rncr(ByVal N&, ByVal K&) As Double
'
'   Calcola i coefficienti binomiali Cn,k come:
'    rncr = N! / (K! * (N - K)!)
'
'   Nota: La funzione ha senso solo per 0 < N, K <= N
'         e 0 <= K.  Nessun errore viene segnalato.
'
    Dim I&, rncr_T#
'
    If ((N < 1) Or (K < 1) Or (N = K)) Then
        rncr = 1#
'
    Else
        rncr_T = 1#
        For I = 1 To N - K
            rncr_T = rncr_T * (1# + CDbl(K) / CDbl(I))
        Next I
'
        rncr = rncr_T
    End If
'
'
'
End Function
Public Sub T_Spline(Pi() As P_Type, ByVal VZ&, Pc() As P_Type)
'
'   Ritorna, nel vettore Pc(), i valori della curva T-Spline.
'   La curva e' calcolata in modo parametrico (0 <= u <= 1)
'   con il valore 0 di u corrispondente a Pc(0) ed il valore
'   1 corrispondente a Pc(NPC_1).
'
'   Parametri:
'       Pi(0 to NPI - 1):   Vettore dei punti, dati, da
'                           interpolare.
'       Pc(0 to NPC - 1):   Vettore dei punti, calcolati,
'                           della curva interpolante.
'       VZ:                 Valore di tensione della curva
'                           (1 <= VZ <= 100): valori grandi
'                           di VZ appiattiscono la curva.
'
    Dim NPI_1&, NPC_1&, I&, J&
    Dim H#, z#, z2i#, szh#, u#, u0#, u1#, du1#, du0#
    Dim s() As P_Type
'
    NPI_1 = UBound(Pi)      ' N. di punti da interpolare - 1.
    NPC_1 = UBound(Pc)      ' N. di punti sulla curva - 1.
    z = CDbl(VZ)
'
    Call Find_TCof(Pi(), NPI_1 + 1, s(), z)
'
    ' La curva inizia sempre da Pi(0) -> u = 0:
    Pc(0).X = Pi(0).X
    Pc(0).Y = Pi(0).Y
'
    H = 1# / CDbl(NPI_1)
    szh = Sinh(z * H)
    z2i = 1# / z / z
    For I = 1 To NPC_1 - 1
        u = CDbl(I) / CDbl(NPC_1)
        J = Int(u * CDbl(NPI_1)) + 1
        If (J > (NPI_1)) Then J = NPI_1
'
        u0 = CDbl(J - 1) / CDbl(NPI_1)
        u1 = CDbl(J) / CDbl(NPI_1)
        du1 = u1 - u
        du0 = u - u0
'
        Pc(I).X = s(J).X * z2i * Sinh(z * du1) / szh + (Pi(J - 1).X - s(J).X * z2i) * du1 / H
        Pc(I).X = Pc(I).X + s(J + 1).X * z2i * Sinh(z * du0) / szh + (Pi(J).X - s(J + 1).X * z2i) * du0 / H
    
        Pc(I).Y = s(J).Y * z2i * Sinh(z * du1) / szh + (Pi(J - 1).Y - s(J).Y * z2i) * du1 / H
        Pc(I).Y = Pc(I).Y + s(J + 1).Y * z2i * Sinh(z * du0) / szh + (Pi(J).Y - s(J + 1).Y * z2i) * du0 / H
    Next I
'
    ' La curva finisce sempre su Pi(NPI_1) -> u = 1:
    Pc(NPC_1).X = Pi(NPI_1).X
    Pc(NPC_1).Y = Pi(NPI_1).Y
'
'
'
End Sub
Private Sub Find_TCof(Pi() As P_Type, ByVal NPI&, s() As P_Type, ByVal z#)
'
'   Find the coefficients of the T-Spline
'   using constant interval:
'
    Dim I&, H#, a0#, b0#, zh#, z2#
'
    ReDim s(1 To NPI) As P_Type, f(1 To NPI) As P_Type
    ReDim a(1 To NPI) As Double, B(1 To NPI) As Double, C(1 To NPI) As Double
'
    H = 1# / CDbl(NPI - 1)
    zh = z * H
    a0 = 1# / H - z / Sinh(zh)
    b0 = z * 2# * Cosh(zh) / Sinh(zh) - 2# / H
    For I = 1 To NPI - 2
        a(I) = a0
        B(I) = b0
        C(I) = a0
    Next I
'
    z2 = z * z / H
    For I = 1 To NPI - 2
        f(I).X = (Pi(I + 1).X - 2# * Pi(I).X + Pi(I - 1).X) * z2
        f(I).Y = (Pi(I + 1).Y - 2# * Pi(I).Y + Pi(I - 1).Y) * z2
    Next I
'
    Call TRIDAG(a(), B(), C(), f(), s(), NPI - 2)
    For I = 1 To NPI - 2
        s(NPI - I).X = s(NPI - 1 - I).X
        s(NPI - I).Y = s(NPI - 1 - I).Y
    Next I
'
    s(1).X = 0#
    s(NPI).X = 0#
    s(1).Y = 0#
    s(NPI).Y = 0#
'
'
'
End Sub
Private Sub Find_CCof(Pi() As P_Type, ByVal NPI&, cof() As P_Type)
'
'   Find the coefficients of the cubic spline
'   using constant interval parameterization:
'
    Dim I&, H#
'
    ReDim s(1 To NPI) As P_Type, f(1 To NPI) As P_Type, cof(1 To 4, 1 To NPI) As P_Type
    ReDim a(1 To NPI) As Double, B(1 To NPI) As Double, C(1 To NPI) As Double
'
    H = 1# / CDbl(NPI - 1)
    For I = 1 To NPI - 2
        a(I) = 1#
        B(I) = 4#
        C(I) = 1#
    Next I
'
    For I = 1 To NPI - 2
        f(I).X = 6# * (Pi(I + 1).X - 2# * Pi(I).X + Pi(I - 1).X) / H / H
        f(I).Y = 6# * (Pi(I + 1).Y - 2# * Pi(I).Y + Pi(I - 1).Y) / H / H
    Next I
'
    Call TRIDAG(a(), B(), C(), f(), s(), NPI - 2)
    For I = 1 To NPI - 2
        s(NPI - I).X = s(NPI - 1 - I).X
        s(NPI - I).Y = s(NPI - 1 - I).Y
    Next I
'
    s(1).X = 0#
    s(NPI).X = 0#
    s(1).Y = 0#
    s(NPI).Y = 0#
    For I = 1 To NPI - 1
        cof(4, I).X = (s(I + 1).X - s(I).X) / 6# / H
        cof(4, I).Y = (s(I + 1).Y - s(I).Y) / 6# / H
        cof(3, I).X = s(I).X / 2#
        cof(3, I).Y = s(I).Y / 2#
        cof(2, I).X = (Pi(I).X - Pi(I - 1).X) / H - (2# * s(I).X + s(I + 1).X) * H / 6#
        cof(2, I).Y = (Pi(I).Y - Pi(I - 1).Y) / H - (2# * s(I).Y + s(I + 1).Y) * H / 6#
        cof(1, I).X = Pi(I - 1).X
        cof(1, I).Y = Pi(I - 1).Y
    Next I
'
'
'
End Sub
Private Sub TRIDAG(a#(), B#(), C#(), f() As P_Type, s() As P_Type, ByVal NPI_2&)
'
'   Solves the tridiagonal linear system of equations:
'
    Dim J&, bet#
    ReDim gam#(1 To NPI_2)
'
    If B(1) = 0 Then Exit Sub
'
    bet = B(1)
    s(1).X = f(1).X / bet
    s(1).Y = f(1).Y / bet
    For J = 2 To NPI_2
        gam(J) = C(J - 1) / bet
        bet = B(J) - a(J) * gam(J)
        If (bet = 0) Then Exit Sub
        s(J).X = (f(J).X - a(J) * s(J - 1).X) / bet
        s(J).Y = (f(J).Y - a(J) * s(J - 1).Y) / bet
    Next J
'
    For J = NPI_2 - 1 To 1 Step -1
        s(J).X = s(J).X - gam(J + 1) * s(J + 1).X
        s(J).Y = s(J).Y - gam(J + 1) * s(J + 1).Y
    Next J
'
'
'
End Sub
Private Function Cosh(ByVal z As Double) As Double
'
'   Ritorna il coseno iperbolico di z#:
'
    Cosh = (Exp(z) + Exp(-z)) / 2#
'
'
'
End Function
Private Function Sinh(ByVal z As Double) As Double
'
'   Ritorna il seno iperbolico di z#:
'
    Sinh = (Exp(z) - Exp(-z)) / 2#
'
'
'
End Function

Antworten