Smooth Curve (Series of Bezier Curves)

Category: Drawing

Date: 02-16-2022

Return to Index


 
'Compilable Example:  (Jose Includes)
#Compiler PBWin 10
#Compile Exe
#Dim All
%Unicode = 1
#Include "Win32API.inc"
 
%IDC_Graphic = 500
%IDC_Button  = 501
 
Global hDlg As Dword, P() As Point, pCount As Long
 
Function PBMain() As Long
   Dialog New Pixels, 0, "Smooth Curve from Series of Points",300,300,400,400, %WS_OverlappedWindow To hDlg
   Control Add Button, hDlg, %IDC_Button, "Clear", 5,5,50,20
   Control Add Graphic, hDlg, %IDC_Graphic, "", 0, 30, 400,400, %SS_Notify
   Graphic Attach hDlg, %IDC_Graphic
   Dialog Show Modal hDlg Call DlgProc
End Function
 
CallBack Function DlgProc() As Long
   Local pt As Point
   Select Case Cb.Msg
      Case %WM_InitDialog
         pCount = 0 : ReDim P(0)
      Case %WM_Command
         Select Case Cb.Ctl
            Case %IDC_Button
               pCount = 0 : ReDim P(0) : Graphic Clear
            Case %IDC_Graphic
               GetCursorPos pt
               ScreenToClient hDlg, pt
               pt.y = pt.y - 30
               ReDim Preserve P(pCount)
               P(pCount) = pt
               If pCount > 2 Then DrawCurves 0.01, 0.5
               Graphic Box (P(pCount).x-5,P(pCount).y-5)-(P(pCount).x+5,P(pCount).y+5),,%Red
               Incr pCount
         End Select
   End Select
End Function
 
Function BX(ByVal t As SingleByVal x0 As SingleByVal x1 As SingleByVal x2 As SingleByVal x3 As SingleAs Single
    Function = x0 * (1 - t) ^ 3  + _
        x1 * 3 * t * (1 - t) ^ 2 + _
        x2 * 3 * t ^ 2 * (1 - t) + _
        x3 * t ^ 3
End Function
 
Function BY(ByVal t As SingleByVal y0 As Single,  ByVal y1 As SingleByVal y2 As SingleByVal y3 As SingleAs Single
    Function = y0 * (1 - t) ^ 3  + _
        y1 * 3 * t * (1 - t) ^ 2 + _
        y2 * 3 * t ^ 2 * (1 - t) + _
        y3 * t ^ 3
End Function
 
Sub DrawBezier(ByVal dt As Single, pt0 As Point, pt1 As Point, pt2 As Point, pt3 As Point)
    Local t,x0,y0,x1,y1 As Single
    ' Draw the control lines.
    Graphic Style 2  'dot
    Graphic Line (pt0.X, pt0.Y)-(pt1.X, pt1.Y), %Red
    Graphic Line (pt2.X, pt2.Y)-(pt3.X, pt3.Y), %Red
    Graphic Style 0  'solid
    ' Draw the curve.
    t = 0
    x1 = BX(t, pt0.X, pt1.X, pt2.X, pt3.X)
    y1 = BY(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y)
    t = t + dt
    Do While t < 1
        x0 = x1 : y0 = y1
        x1 = BX(t, pt0.X, pt1.X, pt2.X, pt3.X)
        y1 = BY(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y)
        Graphic Line  (x0, y0)-(x1, y1), %Blue
        t = t + dt
    Loop
    ' Connect to the final point.
    t = 1
    x0 = x1 : y0 = y1
    x1 = BX(t, pt0.X, pt1.X, pt2.X, pt3.X)
    y1 = BY(t, pt0.Y, pt1.Y, pt2.Y, pt3.Y)
    Graphic Line (x0, y0)-(x1, y1), %Blue
End Sub
 
Sub DrawCurves(ByVal dt As SingleByVal tension As Single)
   Local control_scale As Single, i As Integer
   Local pt,pt_before, pt_after, pt_after2, Di, DiPlus1, p1, p2, p3, p4 As Point
 
   Graphic Clear
    control_scale = CSng(tension / 0.5 * 0.175)
    For i = 0 To UBound(P) - 1
        pt_before = P(Max(i - 1, 0))
        pt = P(i)
        pt_after = P(i + 1)
        pt_after2 = P(Min(i + 2, UBound(P)))
 
        p1 = P(i)
        p4 = P(i + 1)
 
        Di.X = pt_after.X - pt_before.X
        Di.Y = pt_after.Y - pt_before.Y
        p2.X = pt.X + control_scale * Di.X
        p2.Y = pt.Y + control_scale * Di.Y
 
        DiPlus1.X = pt_after2.X - P(i).X
        DiPlus1.Y = pt_after2.Y - P(i).Y
        p3.X = pt_after.X - control_scale * DiPlus1.X
        p3.Y = pt_after.Y - control_scale * DiPlus1.Y
 
        DrawBezier dt, p1, p2, p3, p4
        Graphic Box (P(i).x-5,P(i).y-5)-(P(i).x+5,P(i).y+5),,%Red
    Next i
End Sub
 
'gbs_01410
'Date: 10-17-2014


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm