Autore Topic: Curve di Bezier  (Letto 865 volte)

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Curve di Bezier
« il: 24 Luglio 2014, 23:51:00 »
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, 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. :-\

Codice: [Seleziona]
' 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
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.266
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Curve di Bezier
« Risposta #1 il: 25 Luglio 2014, 18:13:11 »
Ho posto questa questione nel confratello foro spagnolo, ed vi è stata una risposta: è stato suggerito di porre la proprietà ".Cached" della DrawingArea a True .

Il risultato ottenuto è quello mostrato nel file immagine in fondo allegato.

L'amico del foro spagnolo ha comunque sottolineato di non sapere se la curva ottenuta è esattamente quella che tu ti attendevi dal codice.
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Curve di Bezier
« Risposta #2 il: 25 Luglio 2014, 18:53:04 »
Cached è già settata a True, altrimenti mi da errore e non disegna nulla.
Comunque la curva non va ancora bene, dovrebbe girare molto più in basso.
Ci sarebbero dei lintati in C da tradurre, ma qui vado in crisi.
« Ultima modifica: 25 Luglio 2014, 18:54:58 da Top Fuel »
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.266
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Curve di Bezier
« Risposta #3 il: 25 Luglio 2014, 20:30:18 »
Ad ogni modo ho notato che ampliando la dimensione della DrawingArea del progetto del nostro amico spagnolo, si può notare che la curva risulta errata come la precedente. Non è cambiato niente.

« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.266
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Curve di Bezier
« Risposta #4 il: 26 Luglio 2014, 02:30:49 »
Ci sarebbero dei listati in C da tradurre...
Se non sbaglio, la traduzione (con integrazione iniziale) del codice C, presente nella pagina di Wikipedia, in Gambas dovrebbe essere la seguente:   :-X
Codice: gambas [Seleziona]
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
« Ultima modifica: 27 Luglio 2014, 16:33:04 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Curve di Bezier
« Risposta #5 il: 26 Luglio 2014, 15:19:17 »
Proverò a vedere se funziona meglio.
Secondo me se si riuscisse a farla funzionare come si deve sarebbe qualcosa di buono da aggiungere a Gambas, quella originale è un pò troppo limitata.
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline jsbsan

  • Gamberetto
  • *
  • Post: 7
    • Mostra profilo
Re: Curve di Bezier
« Risposta #6 il: 27 Luglio 2014, 13:17:48 »
Lascio qui come mi è stato risolto utilizzando l'equazione parametrica

http://jsbsan.blogspot.com.es/2014/07/dibujando-una-curva-bezier-de-mas-de-3.html


Saluti

Jsbsan

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.266
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Curve di Bezier
« Risposta #7 il: 27 Luglio 2014, 16:30:10 »
Saluti

Jsbsan
Ciao Jsbsan,
...be', adesso mi pare che funzioni proprio bene.  :)
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re: Curve di Bezier
« Risposta #8 il: 27 Luglio 2014, 16:35:31 »
Accidenti, io volevo fare una semplice procedurina ed arrivano con un progetto bello e buono. :D
Grandi. :ok:
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.266
  • Ne mors quidem nos iunget
    • Mostra profilo
Re: Curve di Bezier
« Risposta #9 il: 27 Luglio 2014, 16:45:54 »
...questa è la conferma, semmai vi fosse stato bisogno, dell'estrema utilità dell'interscambio fra i forum e fra i programmatori.   :D
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »