Splines Verständnisfragen

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

Re: Splines Verständnisfragen

Beitrag von SMaag »

hier auch gleich die ersten Übersetzungen

Code: Alles auswählen

Procedure Bezier_C(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva di Bezier calcolata
  ;   al valore t (0 <= t <= 1). La curva e' calcolata in modo
  ;   parametrico con il valore 0 di t corrispondente a PtOut(0)
  ;   ed il valore 1 corrispondente a PtOut(nPOut).
  ;   Questo algoritmo ricalca la forma classica del polinomio
  ;   di Bernstein.
  ;
    Protected.i I, K, nPIn, nPOut, NF
    Protected.d t, BF
    
    nPIn = ArraySize(PtIn())      ; N Points-In
    nPOut = ArraySize(PtOut())    ; n Points-Out
   
    For I = 0 To nPOut
      t = (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(t, K) * Pow((1.0-t), (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
  
  Procedure Bezier_1(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva di Bezier.
  ;   La curva e' calcolata in modo parametrico (0 <= t < 1)
  ;   con il valore 0 di t corrispondente a PtOut(0);
  ;   Attenzione: il punto PtOut(nPOut), corrispondente al valore t = 1,
  ;               non puo; essere calcolato.
  ;
  ;   Parametri:
  ;       PtIn(0 to NPI-1):   Vettore dei punti, dati, da
  ;                           approssimare.
  ;       PtOut(0 to NPC-1):   Vettore dei punti, calcolati,
  ;                           della curva approssimante.
  ; 
    Protected I, K, nPIn, nPOut
    Protected.d t, t1, ue, u_1e, BF
    
    nPIn = ArraySize(PtIn()) ; N. di punti da approssimare - 1.
    nPOut = ArraySize(PtOut()) ; N. di punti sulla curva - 1.
    
    ; La curva inizia sempre da PtIn(0) -> t = 0:
    PtOut(0)\X = PtIn(0)\X
    PtOut(0)\Y = PtIn(0)\Y
    ;PtOut(0)\Z = PtIn(0)\Z  ; for 3D Splines
    
    For I = 1 To nPOut-1
      t = (I) / (nPOut)
      ue = 1.0
      t1 = 1.0-t
      u_1e = Pow(t1, nPIn)
    
      PtOut(I)\X = 0.0
      PtOut(I)\Y = 0.0
      ;PtOut(I)\Z = 0.0
      For K = 0 To nPIn
        BF = _FactorDbl(nPIn, K+1) * ue * u_1e / _FactorDbl(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
    
        ue = ue * t
        u_1e = u_1e / t1
      Next K
    Next I
    
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)
       
  EndProcedure

  Procedure Bezier(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva di Bezier.
  ;   La curva e' calcolata in modo parametrico (0 <= t < 1)
  ;   con il valore 0 di t corrispondente a PtOut(0);
  ;
  ;   Questa versione elimina alcuni problemi di "underflow"
  ;   e di "overflow" presentati dalla Bezier_1 e dalla Bezier_C.
  ;
  ;   Parametri:
  ;       PtIn(0 to NPI-1):   Vettore dei punti, dati, da
  ;                           approssimare.
  ;       PtOut(0 to NPC-1):   Vettore dei punti, calcolati,
  ;                           della curva approssimante.
  ;
    
    Protected.i I, K, nPIn, nPOut
    Protected.d t, ue, BF
     
    nPIn = ArraySize(PtIn())    ; Number of Points  (2 <= nPIn <= 1029).
    nPOut = ArraySize(PtOut())  ; Numger of Points on curve
    
    If ArraySize(BezierCoefficientTable()) < nPIn 
      _InitBezierCoefficientTable(nPIn)  
    EndIf

    ; The curve starts always with  PtIn(0) => t = 0
    PtOut(0) = PtIn(0)
    
    For I = 1 To nPOut-1
      t = I/nPOut
      ue = 1.0
     
      PtOut(I)\X = 0.0
      PtOut(I)\Y = 0.0
      ;PtOut(I)\Z = 0.0  ; for 3D Splines
      
      For K = 0 To nPIn
        BF = BezierCoefficientTable(K) * ue * Pow((1.0-t), (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
    
        Ue = ue * t
      Next K
    Next I
    
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)
   
  EndProcedure
  
  Procedure Bezier_P(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva di Bezier calcolata
  ;   al valore t (0 <= t < 1). La curva e' calcolata in modo
  ;   parametrico con il valore 0 di t corrispondente a PtOut(0);
  ;   Attenzione: il punto PtOut(nPOut), corrispondente al valore t = 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.
  ;
    Protected.i I, K, memK, nPIn, nPOut, NoOfNodes, Node
    Protected.d t, uk, dPow, dBlend
    
    nPIn = ArraySize(PtIn())
    nPOut = ArraySize(PtOut())
    
    For I = 0 To nPOut-1
      t = I / nPOut
      uk = 1.0
      dPow = Pow((1.0-t), nPIn)
      
      PtOut(I)\X = 0
      PtOut(I)\Y = 0
      ;PtOut(I)\Z = 0  ; for 3D Splines
      
      For K = 0 To nPIn
        
        NoOfNodes = nPIn
        memK = K
        Node = nPIn - K
        dBlend = uk * dPow
        uk = uk * t
        dPow = dPow / (1.0-t)
        
        While NoOfNodes >= 1
          dBlend = dBlend * NoOfNodes
          NoOfNodes - 1
          If memK > 1 
            dBlend = dBlend / memK
            memK -1
          EndIf
          If Node > 1 
            dBlend = dBlend / Node
            Node - 1
          EndIf
        Wend
    
        PtOut(I)\X = PtOut(I)\X + PtIn(K)\X * dBlend
        PtOut(I)\Y = PtOut(I)\Y + PtIn(K)\Y * dBlend
        ;PtOut(I)\Z = PtOut(I)\Z + PtIn(K)\Z * dBlend  ; for 3D Splines
      Next
    Next
    
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)

  EndProcedure
  
  Procedure C_Spline(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1))
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva C-Spline.
  ;   La curva e' calcolata in modo parametrico (0 <= t <= 1)
  ;   con il valore 0 di t corrispondente a PtOut(0) ed il valore
  ;   1 corrispondente a PtOut(nPOut).
  ;
  ;   Parametri:
  ;       PtIn(0 to NPI - 1):   Vettore dei punti, dati, da
  ;                           interpolare.
  ;       PtOut(0 to NPC - 1):   Vettore dei punti, calcolati,
  ;                           della curva interpolante.
  ;
    Protected.i nPIn, nPOut, I, J
    Protected.d t, ui
    Dim cof.TPoint2D(0,0) 
    
    nPIn = ArraySize(PtIn())      ; N. di punti da interpolare - 1.
    nPOut = ArraySize(PtOut())      ; N. di punti sulla curva - 1.
    
    _Find_CCof(PtIn(), nPIn+1, cof())
    
    ; The curve starts always with  PtIn(0) => t = 0
    PtOut(0) = PtIn(0)
   
    For I = 1 To nPOut-1
      t = I / nPOut
      J = Int(t * nPIn) + 1
      
      If J > nPIn : J = nPIn : EndIf
      
      ui = t - (J-1)/nPIn
    
      PtOut(I)\X = cof(3, J)\X * _mac_Exp3(ui) + cof(2, J)\X * _mac_Exp2(ui) + cof(1, J)\X * ui + cof(0, J)\X
      PtOut(I)\Y = cof(3, J)\Y * _mac_Exp3(ui) + cof(2, J)\Y * _mac_Exp2(ui) + cof(1, J)\Y * ui + cof(0, J)\Y
      ;PtOut(I)\Z = cof(3, J)\Z * _mac_Exp3(ui) + cof(2, J)\Z * _mac_Exp2(ui) + cof(1, J)\Z * ui + cof(0, J)\Z  ; for 3D Splines
   Next I
    
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)
  EndProcedure

  Procedure B_Spline(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1), Nodes.i)
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva B-Spline.
  ;   La curva e' calcolata in modo parametrico (0 <= t <= 1)
  ;   con il valore 0 di t corrispondente a PtOut(0) ed il valore
  ;   1 corrispondente a PtOut(nPOut).
  ;
  ;   Parametri:
  ;       PtIn(0 to NPI - 1):   Vettore dei punti, dati, da
  ;                           approssimare.
  ;       PtOut(0 to NPC - 1):   Vettore dei punti, calcolati,
  ;                           della curva approssimante.
  ;       Nodes:                 Numero di nodi della curva
  ;                           approssimante:
  ;                           Nodes = 2    -> segmenti di retta.
  ;                           Nodes = 3    -> curve quadratiche.
  ;                           ..   .       ..................
  ;                           Nodes = NPI  -> splines di Bezier.
  
    Protected.i nPIn, nPOut, I, J 
    Protected.d tmax, t, ut
    Dim bn.d(0)
    #Eps = 0.0000001
    
    nPIn = ArraySize(PtIn())  ; N. di punti da approssimare - 1.
    nPOut = ArraySize(PtOut())  ; N. di punti sulla curva - 1.
    tmax = nPIn - Nodes + 2
  
    ; The curve starts always with  PtIn(0) => t = 0
    PtOut(0)\X = PtIn(0)\X
    PtOut(0)\Y = PtIn(0)\Y
    ; PtOut(0)\Z = PtIn(0)\Z  ; for 3D Splines   
  
    For I = 1 To nPOut-1
      t = I / nPOut
      ut = t * tmax
      If Abs(ut - (nPIn + Nodes-2)) <= #Eps 
        PtOut(I)\X = PtIn(nPIn)\X
        PtOut(I)\Y = PtIn(nPIn)\Y
        ;PtOut(I)\Z = PtIn(nPIn)\Z  ; for 3D Spline
      Else
        _B_Basis(nPIn, ut, Nodes, bn())
        For J = 0 To nPIn
          PtOut(I)\X = PtIn(J)\X * bn(J)
          PtOut(I)\Y = PtIn(J)\Y * bn(J)
          ;PtOut(I)\Z = PtIn(J)\Z * bn(J)  ; for 3D Spline
        Next J
      EndIf
    Next I
  
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)
  
  EndProcedure
  
  Procedure T_Spline(Array PtOut.TPoint2D(1), Array PtIn.TPoint2D(1), VZ.i)
  ;
  ;   Ritorna, nel vettore PtOut(), i valori della curva T-Spline.
  ;   La curva e' calcolata in modo parametrico (0 <= t <= 1)
  ;   con il valore 0 di t corrispondente a PtOut(0) ed il valore
  ;   1 corrispondente a PtOut(nPOut).
  ;
  ;   Parametri:
  ;       PtIn(0 to NPI - 1):   Vettore dei punti, dati, da
  ;                           interpolare.
  ;       PtOut(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.
  ;
    Protected.i nPIn, nPOut, I, J
    Protected.d H, z, z2i, szh, t, u0, t1, du1, du0
    Dim s.TPoint2D(1)
    
    nPIn = ArraySize(PtIn())        ; N. di punti da interpolare - 1.
    nPOut = ArraySize(PtOut())      ; N. di punti sulla curva - 1.
    z = (VZ)
    
    _Find_TCof(PtIn(), nPIn+1, s(), z)
    
    ; The curve starts always with  PtIn(0) => t = 0
    PtOut(0)\X = PtIn(0)\X
    PtOut(0)\Y = PtIn(0)\Y
    ;PtOut(0)\Z = PtIn(0)\Z ; for 3D Spline
    
    H = 1.0 / (nPIn)
    szh = SinH(z * H)
    z2i = 1.0 / z / z
    For I = 1 To nPOut-1
      t = (I) / (nPOut)
      J = Int(t * (nPIn)) + 1
      If (J > (nPIn)) 
        J = nPIn
      EndIf
      
      u0 = (J-1) / nPIn
      t1 = J / nPIn
      du1 = t1 - t
      du0 = t - u0
    
      PtOut(I)\X = s(J)\X * z2i * SinH(z * du1) / szh + (PtIn(J-1)\X - s(J)\X * z2i) * du1 / H
      PtOut(I)\X = PtOut(I)\X + s(J+1)\X * z2i * SinH(z * du0) / szh + (PtIn(J)\X - s(J+1)\X * z2i) * du0 / H
    
      PtOut(I)\Y = s(J)\Y * z2i * SinH(z * du1) / szh + (PtIn(J-1)\Y - s(J)\Y * z2i) * du1 / H
      PtOut(I)\Y = PtOut(I)\Y + s(J+1)\Y * z2i * SinH(z * du0) / szh + (PtIn(J)\Y - s(J+1)\Y * z2i) * du0 / H
      
      ;PtOut(I)\Z = s(J)\Z * z2i * SinH(z * du1) / szh + (PtIn(J-1)\Z - s(J)\Z * z2i) * du1 / H
      ;PtOut(I)\Z = PtOut(I)\Z + s(J+1)\Z * z2i * SinH(z * du0) / szh + (PtIn(J)\Z - s(J+1)\Z * z2i) * du0 / H
   Next I
    
    ; Last Point on curve = PtIn(nPin) => t = 1 
    PtOut(nPOut) = PtIn(nPIn)
  EndProcedure    

und die Coeffizeinten Funktionen

Code: Alles auswählen

Procedure _TRIDAG(Array a.d(1), Array B.d(1), Array C.d(1), Array f.TPoint2D(1), Array s.TPoint2D(1),  NPI_2.i)
  ;
  ;   Solves the tridiagonal linear system of equations:
  ;
    Protected.i J
    Protected.d bet
    
    Dim gam.d(NPI_2)  ; we need 1 to NPI_2
  
    If B(1) = 0 
      ProcedureReturn
    EndIf
    
    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) 
          ProcedureReturn
        EndIf  
          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
  EndProcedure
  
  Procedure _Find_CCof(Array PtIn.TPoint2D(1),  NPI.i, Array cof.TPoint2D(2))
  ;
  ;   Find the coefficients of the cubic spline
  ;   using constant interval parameterization:
  ;
    Protected.i I
    Protected.d H
    
    ReDim cof.TPoint2D(4, NPI) ; we need only (1..4, 1..NPI)
    Dim s.TPoint2D(NPI)       ; (1..NPI)
    Dim f.TPoint2D(NPI)       ; (1..NPI)
    
    Dim a.d(NPI)   ; (1..NPI)
    Dim B.d(NPI)   ; (1..NPI)
    Dim C.d(NPI)   ; (1..NPI)
  
    H = 1.0 / (NPI-1)
    For  I= 1 To NPI - 2
      a(I) = 1.0
      B(I) = 4.0
      C(I) = 1.0
    Next I
  
    For I = 1 To NPI - 2
      f(I)\X = 6.0 * (PtIn(I + 1)\X - 2.0 * PtIn(I)\X + PtIn(I-1)\X) / H / H
      f(I)\Y = 6.0 * (PtIn(I + 1)\Y - 2.0 * PtIn(I)\Y + PtIn(I-1)\Y) / H / H
    Next I
  
    _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.0
    s(NPI)\X = 0.0
    s(1)\Y = 0.0
    s(NPI)\Y = 0.0
    For I = 1 To NPI-1
      cof(3, I)\X = (s(I+1)\X - s(I)\X) / 6.0 / H
      cof(3, I)\Y = (s(I+1)\Y - s(I)\Y) / 6.0 / H
      cof(2, I)\X = s(I)\X / 2.0
      cof(2, I)\Y = s(I)\Y / 2.0
      cof(1, I)\X = (PtIn(I)\X - PtIn(I-1)\X) / H - (2.0 * s(I)\X + s(I+1)\X) * H / 6.0
      cof(1, I)\Y = (PtIn(I)\Y - PtIn(I-1)\Y) / H - (2.0 * s(I)\Y + s(I+1)\Y) * H / 6.0
      cof(0, I)\X = PtIn(I-1)\X
      cof(0, I)\Y = PtIn(I-1)\Y
    Next I
  EndProcedure
  
  Procedure _Find_TCof(Array PtIn.TPoint2D(1),  NPI, Array s.TPoint2D(1),  z.d)
  ;
  ;   Find the coefficients of the T-Spline
  ;   using constant interval:
  ;
    Protected.i I
    Protected.d H, a0, b0, zh, z2
  
    ReDim s(NPI)          ; we need (1..NPI)
    Dim f.TPoint2D(NPI)   ; we need (1..NPI)
    Dim a.d(NPI)          ; we need (1..NPI)
    Dim B.d(NPI)          ; we need (1..NPI)
    Dim C.d(NPI)          ; we need (1..NPI)
  
    H = 1.0 / (NPI-1)
    zh = z * H
    a0 = 1.0 / H - z / SinH(zh)
    b0 = z * 2.0 * CosH(zh) / SinH(zh) - 2.0 / 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 = (PtIn(I+1)\X - 2.0 * PtIn(I)\X + PtIn(I-1)\X) * z2
      f(I)\Y = (PtIn(I+1)\Y - 2.0 * PtIn(I)\Y + PtIn(I-1)\Y) * z2
    Next I
  
    _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.0
    s(NPI)\X = 0.0
    s(1)\Y = 0.0
    s(NPI)\Y = 0.0
  EndProcedure
Antworten