dev/qt/ NaiveBezier


This is an example of drawing a Bezier curve the 'naive' way, that is, we use lerping (linear interpolation) recursively. For an excellent youtube video on how Bezier's work, see Freya Holmér's video here.

The Code

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import sys

app = QApplication(sys.argv)

def lerp(x0,x1,t):
  'lerp between two vectors'
  res = tuple(lerpx(x0[i],x1[i],t) for i in range(len(x0)))
  return res

def lerpx(x,y,t):
  'lerp between two real numbers'
  return x + t*(y-x)

class B(QWidget):
  def __init__(self):
    super().__init__()
    self.resize(640,480)
    self.pts = ((10,10),(20,300),(300,45),(500,350))
  def paintEvent(self,e):
    # draw the bezier the naive way by recursively lerping
    n = 100
    dt = 1.0/n

    # compute the points of the curve
    curve = []
    for j in range(n+1): # n+1 so we include the endpoint
      t = j*dt
      pts = self.pts
      while len(pts) > 1:
        # use lerping to get from n points to n-1, and stop when only one point remains
        pts = tuple(lerp(pts[i],pts[i+1],t) for i in range(len(pts)-1))
      curve.append(pts[0])

    # clear the window and draw our curve
    with QPainter(self) as p:
      w = self.width()
      h = self.height()
      p.fillRect(0,0,w,h,QColor(255,255,255)) # clear the window
      path = QPainterPath()
      x = curve[0]
      path.moveTo(x[0],x[1])
      for x in curve[1:]:
        path.lineTo(x[0],x[1]) # connect our points with lines
      p.setBrush(QColor(0,0,0,0))
      p.setPen(QPen(QColor(0,0,0),3))
      p.drawPath(path)

b = B()
b.show()
app.exec()