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
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