Potreste darmi una mano a risolvere un problema da cui non riesco ad uscire?
Tramite il metodo CurveTo in Gambas si può disegnare una curva di Bezier, ma solo cubica (a 4 punti di controllo). Leggendo la pagina Wikipedia sull'argomento: http://it.wikipedia.org/wiki/Curve_Bezi%C3%A8r (http://it.wikipedia.org/wiki/Curve_Bezi%C3%A8r), ho trovato un programma in VB che ho provato ad adattare a Gambas con una funzione per poter disegnare delle curve fino a 255 punti di controllo, ma la curva non rimane dentro i punti di controllo, ma deborda, come potrete vedere usando l'esempio qui sotto, disegnato in una DrawingArea di 1000x700.
Ho provato a fare delle modifiche qua e la ma senza risultati apprezzabili. Magari voi che siete più bravi di me riuscite a trovare dove sta la gabola. :-\
' Gambas class file
Public Struct PuntoBezier
x As Float
y As Float
End Struct
Private punti As New PuntoBezier[]
Private bxn As New Float[]
Private cxn As New Float[]
Private byn As New Float[]
Private cyn As New Float[]
Public Sub _new()
'un esempio con 5 punti di controllo
Dim punto As PuntoBezier
punto = New PuntoBezier
punto.x = 20
punto.y = 600
punti.Add(punto)
punto = New PuntoBezier
punto.x = 200
punto.y = 110
punti.Add(punto)
punto = New PuntoBezier
punto.x = 500
punto.y = 450
punti.Add(punto)
punto = New PuntoBezier
punto.x = 800
punto.y = 600
punti.Add(punto)
punto = New PuntoBezier
punto.x = 950
punto.y = 200
punti.Add(punto)
punto = New PuntoBezier
punto.x = 650
punto.y = 50
punti.Add(punto)
End
Public Sub Form_Open()
Me.Center
Bezier
End
Public Sub Bezier()
Dim ax, bx, cx, ay, by, cy, xt, yt, axn, ayn, xtn, ytn, t As Float
Dim totpunti, x As Byte
totpunti = punti.Count
If totpunti = 1 Then
Message.Info("Un punto di controllo non basta\nNon posso andare avanti", " Fine")
Return
Endif
bxn = New Float[totpunti]
cxn = New Float[totpunti]
byn = New Float[totpunti]
cyn = New Float[totpunti]
With Paint
.Begin(Area)
.LineWidth = 1
.MoveTo(punti[0].x, punti[0].y)
.Brush = Paint.Color(Color.Green)
For x = 1 To totpunti - 1
.LineTo(punti[x].x, punti[x].y)
Next
.Stroke
.MoveTo(punti[0].x, punti[0].y)
Select Case totpunti
Case 2
.LineTo(punti[1].x, punti[1].y)
Case 4
.CurveTo(punti[1].x, punti[1].y, punti[2].x, punti[2].y, punti[3].x, punti[3].y)
Case Else
cxn[0] = 0
For x = 1 To totpunti - 1
cxn[x] = (totpunti - 1) * (punti[x].x - punti[x - 1].x) - cxn[x - 1]
Next
axn = punti[totpunti - 1].x - punti[0].x
For x = 1 To totpunti - 1
axn -= cxn[x]
Next
cyn[0] = 0
For x = 1 To totpunti - 1
cyn[x] = (totpunti - 1) * (punti[x].y - punti[x - 1].y) - cyn[x - 1]
Next
ayn = punti[totpunti - 1].y - punti[0].y
For x = 1 To totpunti - 1
ayn -= cyn[x]
Next
For t = 0 To 1 Step 0.0001
xtn = axn * t ^ (totpunti - 1)
ytn = ayn * t ^ (totpunti - 1)
For x = totpunti - 1 To 1 Step -1
xtn += cxn[x] * t ^ x
ytn += cyn[x] * t ^ x
Next
xtn += punti[0].x
ytn += punti[0].y
Draw.Begin(Area)
Draw.Foreground = Color.Red
Draw.Point(xtn, ytn)
Draw.End
Next
End Select
.Stroke
.End
End With
End
Ci sarebbero dei listati in C da tradurre...
Se non sbaglio, la traduzione (con integrazione iniziale) del codice C, presente nella pagina di Wikipedia (http://it.wikipedia.org/wiki/Curve_Bezi%C3%A8r#Applicazioni_nella_computer_grafica), in Gambas dovrebbe essere la seguente: :-X
Public Struct Point2D
xs As Single
ys As Single
End Struct
Public Sub Form_Open()
Dim dt As Single
Dim i, numberOfPoints As Integer
Dim cp, curve As New Point2D[4]
numberOfPoints = 4
With cp[0] = New Point2D
.xs = ' valore
.ys = ' valore
End With
With cp[1] = New Point2D
.xs = ' valore
.ys = ' valore
End With
With cp[2] = New Point2D
.xs = ' valore
.ys = ' valore
End With
With cp[3] = New Point2D
.xs = ' valore
.ys = ' valore
End With
dt = 1.0 / (numberOfPoints - 1)
For i = 0 To numberOfPoints - 1
curve[i] = PointOnCubicBezier(cp, i * dt)
Next
End
Private Function PointOnCubicBezier(cp As Point2D[], t As Single) As Point2D
Dim ax, bx, cx As Single
Dim ay, by, cy As Single
Dim tSquared, tCubed As Single
Dim result As New Point2D
' Calcolo dei coefficienti del polinomio:
cx = 3.0 * (cp[1].xs - cp[0].xs)
bx = 3.0 * (cp[2].xs - cp[1].xs) - cx
ax = cp[3].xs - cp[0].xs - cx - bx
cy = 3.0 * (cp[1].ys - cp[0].ys)
by = 3.0 * (cp[2].ys - cp[1].ys) - cy
ay = cp[3].ys - cp[0].ys - cy - by
' Calcolo del punto della curva in relazione a t:
tSquared = t * t
tCubed = tSquared * t
result.xs = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].xs
result.ys = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].ys
Return result
End