March 05, 2021, 07:16:09 AM

Author Topic: [bmx] Quadratic and Cubic Bezier Curves by ImaginaryHuman [ 1+ years ago ]  (Read 421 times)

Offline BlitzBot

Title : Quadratic and Cubic Bezier Curves
Author : ImaginaryHuman
Posted : 1+ years ago

Description : Here is a simple little demo showing how to calculate and draw bezier curves using a slightly modified De Casteljau algorithm. This should be more efficient that the traditional equation-based approach and is much easier to understand. In the demo I also am also forcing the shared point P3 between two quadratic beziers to vaguely emulate a cubic bezier, but then in red you can see a real cubic bezier and how its shape differs to the quadratic one.

Code :
Code: BlitzMax
  1. Strict
  2.  
  3. Local NumberOfSegments:Int=50
  4.  
  5. SetGraphicsDriver GLMax2DDriver()
  6. Graphics 800,600
  7. glEnable(GL_LINE_SMOOTH)
  8. glHint(GL_LINE_SMOOTH_HINT,GL_NICEST)
  9. glLineWidth(2.0)
  10. SetBlend LIGHTBLEND
  11. 'SetClsColor $FF,$FF,$FF
  12.  
  13. Local PX:Float[5]
  14. Local PY:Float[5]
  15. PX[0]=50
  16. PY[0]=550
  17. PX[1]=225
  18. PY[1]=50
  19. PX[2]=370
  20. PY[2]=300
  21. PX[3]=525
  22. PY[3]=575
  23. PX[4]=750
  24. PY[4]=50
  25.  
  26. Local Position:Float
  27. Local X:Float
  28. Local Y:Float
  29. Local X2:Float
  30. Local Y2:Float
  31. Local Controlling:Int=False
  32. Local ControlPoint:Int=0
  33. Local MX:Int
  34. Local MY:Int
  35. Local Point:Int
  36. Local SegmentSize:Float=1.0/NumberOfSegments
  37. Repeat
  38.         Cls
  39.        
  40.         'Control it
  41.         MX=MouseX()
  42.         MY=MouseY()
  43.         If Controlling=False
  44.                 If MouseDown(1)
  45.                         For Point=0 To 4
  46.                                 If MX>=PX[Point]-15 And MY>=PY[Point]-15 And MX<=PX[Point]+15 And MY<=PY[Point]+15 And Point<>2
  47.                                         'Control the point so long as it's not the middle shared point
  48.                                         Controlling=True
  49.                                         ControlPoint=Point
  50.                                 EndIf
  51.                         Next
  52.                 Else
  53.                         Controlling=False
  54.                 EndIf
  55.         EndIf  
  56.         If Controlling=True
  57.                 SetColor $0,$0,$0
  58.                 DrawText MX+","+MY,0,32
  59.                 PX[ControlPoint]=MX
  60.                 PY[ControlPoint]=MY
  61.                 If Not MouseDown(1) Then Controlling=False
  62.         EndIf
  63.  
  64.         'Force continuity - calculate the middle shared point automatically
  65.         PX[2]=PX[1]+((PX[3]-PX[1])*0.5)
  66.         PY[2]=PY[1]+((PY[3]-PY[1])*0.5)
  67.  
  68.         'Draw stuff
  69.         SetColor $88,$88,$88
  70.         DrawLine PX[0],PY[0],PX[1],PY[1]        'Draw lines
  71.         DrawLine PX[1],PY[1],PX[2],PY[2]
  72.         DrawLine PX[2],PY[2],PX[3],PY[3]
  73.         DrawLine PX[3],PY[3],PX[4],PY[4]
  74.         SetColor $FF,$0,$0
  75.         DrawOval PX[0]-5,PY[0]-5,10,10  'Draw control points
  76.         DrawOval PX[1]-5,PY[1]-5,10,10
  77.         'DrawOval PX[2]-5,PY[2]-5,10,10 'Don't draw middle shared point
  78.         DrawOval PX[3]-5,PY[3]-5,10,10
  79.         DrawOval PX[4]-5,PY[4]-5,10,10
  80.         SetColor 121,195,3
  81.        
  82.         'Draw curve 1 quadratic
  83.         X=PX[0]
  84.         Y=PY[0]
  85.         Position=SegmentSize
  86.         While Position<=1.00001 'Go to 1.00001 to make sure final line is drawn
  87.                 Curve3(PX[0],PY[0],PX[1],PY[1],PX[2],PY[2],Position,X2,Y2)
  88.                 DrawLine X,Y,X2,Y2
  89.                 X=X2
  90.                 Y=Y2
  91.                 Position:+SegmentSize
  92.         Wend
  93.        
  94.         'Draw curve 2 quadratic
  95.         X=PX[2]
  96.         Y=PY[2]
  97.         Position=SegmentSize
  98.         While Position<=1.00001 'Go to 1.00001 to make sure final line is drawn
  99.                 Curve3(PX[2],PY[2],PX[3],PY[3],PX[4],PY[4],Position,X2,Y2)
  100.                 DrawLine X,Y,X2,Y2
  101.                 X=X2
  102.                 Y=Y2
  103.                 Position:+SegmentSize
  104.         Wend
  105.  
  106.         'Draw total curve as cubic bezier
  107.         SetColor $FF,$00,$00
  108.         X=PX[0]
  109.         Y=PY[0]
  110.         Position=SegmentSize
  111.         While Position<=1.00001 'Go to 1.00001 to make sure final line is drawn
  112.                 Curve4(PX[0],PY[0],PX[1],PY[1],PX[3],PY[3],PX[4],PY[4],Position,X2,Y2)
  113.                 DrawLine X,Y,X2,Y2
  114.                 X=X2
  115.                 Y=Y2
  116.                 Position:+SegmentSize
  117.         Wend
  118.  
  119.         Flip 1
  120. Until KeyHit(KEY_ESCAPE) Or AppTerminate()
  121.  
  122. Function Curve3(P1X:Float,P1Y:Float,P2X:Float,P2Y:Float,P3X:Float,P3Y:Float,Position:Float,PointX:Float Var,PointY:Float Var)
  123.         'Calculate a point on a bezier curve with 3 control points (quadratic) using floating point math
  124.         'Requires three control points with X and Y coordinates and a current position on the curve in the range 0..1
  125.         'Coordinates are returned in PointX and PointY variables
  126.  
  127.         'Calculate position along each line between pairs of control points P1-to-P2 and P2-to-P3
  128.         P1X:+((P2X-P1X)*Position)                                       'P1 to P2 X, scaled, absolute
  129.         P1Y:+((P2Y-P1Y)*Position)                                       'P1 to P2 Y, scaled, absolute
  130.         P2X:+((P3X-P2X)*Position)                                       'P2 to P3 X, scaled, absolute
  131.         P2Y:+((P3Y-P2Y)*Position)                                       'P2 to P3 Y, scaled absolute
  132.  
  133.         'Calculate position along final line between P12 and P23
  134.         PointX=((P2X-P1X)*Position)+P1X                 'P12 to P23 X, scaled, absolute
  135.         PointY=((P2Y-P1Y)*Position)+P1Y                 'P12 to P23 Y, scaled, absolute
  136. End Function
  137.  
  138. Function Curve4(P1X:Float,P1Y:Float,P2X:Float,P2Y:Float,P3X:Float,P3Y:Float,P4X:Float,P4Y:Float,Position:Float,PointX:Float Var,PointY:Float Var)
  139.         'Calculate a point on a bezier curve with 4 control points (cubic) using floating point math
  140.         'Requires four control points with X and Y coordinates and a current position on the curve in the range 0..1
  141.         'Coordinates are returned in PointX and PointY variables
  142.  
  143.         'Calculate position along each line between pairs of control points P1-to-P2, P2-to-P3, P3-to-P4
  144.         P1X:+((P2X-P1X)*Position)                                       'P1 to P2 X, scaled, absolute
  145.         P1Y:+((P2Y-P1Y)*Position)                                       'P1 to P2 Y, scaled, absolute
  146.         P2X:+((P3X-P2X)*Position)                                       'P2 to P3 X, scaled, absolute
  147.         P2Y:+((P3Y-P2Y)*Position)                                       'P2 to P3 Y, scaled, absolute
  148.         P3X:+((P4X-P3X)*Position)                                       'P3 to P4 X, scaled, absolute
  149.         P3Y:+((P4Y-P3Y)*Position)                                       'P3 to P4 Y, scaled, absolute
  150.  
  151.         'Calculate position along intermediary lines between P12-to-P23 and P23-to-P34
  152.         P1X:+((P2X-P1X)*Position)                                       'P12 to P23 X, scaled, absolute
  153.         P1Y:+((P2Y-P1Y)*Position)                                       'P12 to P23 Y, scaled, absolute
  154.         P2X:+((P3X-P2X)*Position)                                       'P23 to P34 X, scaled, absolute
  155.         P2Y:+((P3Y-P2Y)*Position)                                       'P23 to P34 Y, scaled, absolute
  156.  
  157.         'Calculate position along final lines between P123 and P234
  158.         PointX=((P2X-P1X)*Position)+P1X                 'P123 to P234 X, scaled, absolute
  159.         PointY=((P2Y-P1Y)*Position)+P1Y                 'P123 to P234 Y, scaled, absolute
  160. End Function


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal