[PYTHON] I wanted to play with the Bezier curve

at first

I wanted to draw a Bezier curve using python, and I was able to draw it immediately. After that, I wanted to play with the Bezier curve interactively, but I couldn't find the code, so I'll post it including a memorandum for myself. Figure-1-2019-11-22-17-45-07.gif

Bezier curve

For the three-dimensional Bezier curve, I referred to the formula of this person.

matplotlib For the part to be displayed interactively, I referred to this person. Every time the control point is updated, the calculation is recalculated and the curve is displayed again.

easy explanation

On the left are control points and Bezier curves. The radius of curvature is displayed on the right. The x-axis of the graph on the right is t (0 <= t <= 1) and the y-axis is the radius of curvature.

code

bezier.py


from scipy import integrate
import matplotlib.pyplot as plt
import numpy as np

class Coo():
    def __init__(self,_x,_y):
        self.x = _x
        self.y = _y

class Bezier():
    def __init__(self,_p0,_p1,_p2,_p3):
        self.p = [0]*4
        self.p[0] = _p0
        self.p[1] = _p1
        self.p[2] = _p2
        self.p[3] = _p3

        self.fig = plt.figure(figsize=(10,5))
        self.ax = self.fig.add_subplot(121)#111 1x1 
        self.ax.set_xlim(-1.0 , 11.0)
        self.ax.set_ylim(-1.0 , 11.0)

        self.dax = self.fig.add_subplot(122)#111 1x1 

        self.t = np.arange(0,1,0.01)
        
        self.x = (self.t**3)*self.p[3].x + 3*(self.t**2)*(1-self.t)*self.p[2].x + 3*self.t*((1-self.t)**2)*self.p[1].x + ((1-self.t)**3)*self.p[0].x
        self.y = (self.t**3)*self.p[3].y + 3*(self.t**2)*(1-self.t)*self.p[2].y + 3*self.t*((1-self.t)**2)*self.p[1].y + ((1-self.t)**3)*self.p[0].y
        
        self.dx = 3*((self.t**2)*(self.p[3].x-self.p[2].x)+2*self.t*(1-self.t)*(self.p[2].x-self.p[1].x)+((1-self.t)**2)*(self.p[1].x-self.p[0].x))
        self.dy = 3*((self.t**2)*(self.p[3].y-self.p[2].y)+2*self.t*(1-self.t)*(self.p[2].y-self.p[1].y)+((1-self.t)**2)*(self.p[1].y-self.p[0].y))

        self.ddx = 6*(self.t*(self.p[3].x-2*self.p[2].x+self.p[1].x)+(1-self.t)*(self.p[2].x-2*self.p[1].x+self.p[0].x))
        self.ddy = 6*(self.t*(self.p[3].y-2*self.p[2].y+self.p[1].y)+(1-self.t)*(self.p[2].y-2*self.p[1].y+self.p[0].y))

        self.artists = [0]*4
        self.artists[0], = self.ax.plot([self.p[0].x],[self.p[0].y],marker='.',markersize=10,picker=15,label='p[0]')
        self.artists[1], = self.ax.plot([self.p[1].x],[self.p[1].y],marker='.',markersize=10,picker=15,label='p[1]')
        self.artists[2], = self.ax.plot([self.p[2].x],[self.p[2].y],marker='.',markersize=10,picker=15,label='p[2]')
        self.artists[3], = self.ax.plot([self.p[3].x],[self.p[3].y],marker='.',markersize=10,picker=15,label='p[3]')
        self.ax_artist, = self.ax.plot(self.x,self.y)

        dp = [((x_a-x_b)**2 + (y_a-y_b)**2)*100 for x_a,x_b,y_a,y_b in zip(self.x[:-1],self.x[1:],self.y[:-1],self.y[1:])]
        adp = [(i**2 + j**2)**0.5 for i,j in zip(self.dx,self.dy)]
        addp = [(i**2 + j**2)**0.5 for i,j in zip(self.ddx,self.ddy)]
        R = ((self.dx**2 + self.dy**2)**1.5)/((self.dx*self.ddy - self.ddx*self.dy)**2)**0.5

        self.dax.set_xlim(-0.1 , 1.5)
        self.dax.set_ylim(-1.0 , 40)
        dp.append(0.0)

        integrate_simps = integrate.simps(self.y, self.x)
        self.dax_artist, = self.dax.plot(self.t,R)

        dp_max_index = [i for i, x in enumerate(dp) if x == max(dp)]
        adp_max_index = [i for i, x in enumerate(adp) if x == max(adp)]

    def change(self):
        self.x = (self.t**3)*self.p[3].x + 3*(self.t**2)*(1-self.t)*self.p[2].x + 3*self.t*((1-self.t)**2)*self.p[1].x + ((1-self.t)**3)*self.p[0].x
        self.y = (self.t**3)*self.p[3].y + 3*(self.t**2)*(1-self.t)*self.p[2].y + 3*self.t*((1-self.t)**2)*self.p[1].y + ((1-self.t)**3)*self.p[0].y
        
        self.dx = 3*((self.t**2)*(self.p[3].x-self.p[2].x)+2*self.t*(1-self.t)*(self.p[2].x-self.p[1].x)+((1-self.t)**2)*(self.p[1].x-self.p[0].x))
        self.dy = 3*((self.t**2)*(self.p[3].y-self.p[2].y)+2*self.t*(1-self.t)*(self.p[2].y-self.p[1].y)+((1-self.t)**2)*(self.p[1].y-self.p[0].y))

        self.ddx = 6*(self.t*(self.p[3].x-2*self.p[2].x+self.p[1].x)+(1-self.t)*(self.p[2].x-2*self.p[1].x+self.p[0].x))
        self.ddy = 6*(self.t*(self.p[3].y-2*self.p[2].y+self.p[1].y)+(1-self.t)*(self.p[2].y-2*self.p[1].y+self.p[0].y))
        
        dp = [((x_a-x_b)**2 + (y_a-y_b)**2)*100 for x_a,x_b,y_a,y_b in zip(self.x[:-1],self.x[1:],self.y[:-1],self.y[1:])]
        adp = [(i**2 + j**2)**0.5 for i,j in zip(self.dx,self.dy)]
        addp = [(i**2 + j**2)**0.5 for i,j in zip(self.ddx,self.ddy)]
        R = ((self.dx**2 + self.dy**2)**1.5)/((self.dx*self.ddy - self.ddx*self.dy)**2)**0.5

        self.ax_artist.set_data(self.x,self.y)
        self.dax_artist.set_data(self.t,R)

    def sets(self,_gco,_event):
        for i,j in zip(self.artists,self.p):
            if i == _gco:
                i.set_data(_event.xdata,_event.ydata)
                j.x = _event.xdata
                j.y = _event.ydata
                break
        self.change()


gco = None

if __name__ == '__main__':
    a = Coo(1,1)
    b = Coo(10,1)
    c = Coo(1,5)
    d = Coo(10,5)

    B = Bezier(a,b,c,d)
    
    def motion(event):
        global gco
        if gco is None:
            return
        B.sets(gco,event)
        plt.draw()

    def onpick(event):
        global gco
        gco = event.artist


    def release(event):
        global gco
        gco = None

    plt.connect('motion_notify_event', motion)
    plt.connect('pick_event', onpick)
    plt.connect('button_release_event', release)
    
    plt.show()

I'm using only major libraries, so I think it will work soon.

Recommended Posts

I wanted to play with the Bezier curve
I wanted to solve the Panasonic Programming Contest 2020 with Python
I captured the Touhou Project with Deep Learning ... I wanted to.
[Scikit-learn] I played with the ROC curve
I wanted to solve ABC160 with Python
I want to play with aws with python
I wanted to solve ABC172 with Python
I really wanted to copy with selenium
I wanted to solve the ABC164 A ~ D problem with Python
I wanted to solve NOMURA Contest 2020 with Python
I tried to save the data with discord
I wanted to install Python 3.4.3 with Homebrew + pyenv
I wanted to visualize 3D particle simulation with the Python visualization library Matplotlib.
I tried to learn the sin function with chainer
I also wanted to check type hints with numpy
I tried to touch the CSV file with Python
I tried to solve the soma cube with python
I wanted to use the Python library from MATLAB
I want to inherit to the back with python dataclass
I tried to solve the problem with Python Vol.1
I wrote you to watch the signal with Go
I just wanted to extract the data of the desired date and time with Django
I tried to analyze the whole novel "Weathering with You" ☔️
Try to play with the uprobe that supports Systemtap directly
I tried to find the average of the sequence with TensorFlow
I tried to notify the train delay information with LINE Notify
I want to change the Japanese flag to the Palau flag with Numpy
What I did to welcome the Python2 EOL with confidence
[Python] I want to use the -h option with argparse
I can't log in to the admin page with Django3
I tried to divide the file into folders with Python
I wanted to calculate an array with Sympy's subs method
I wanted to delete multiple objects in s3 with boto3
I wanted to run the motor with Raspberry Pi, so I tried using Waveshare's Motor Driver Board
I want to find the intersection of a Bezier curve and a straight line (Bezier Clipping method)
Try to draw a Bezier curve
Hash chain I wanted to avoid (2)
I calculated the stochastic integral (I to integral)
I wanted to evolve cGAN to ACGAN
I liked the tweet with python. ..
I want to do ○○ with Pandas
I want to debug with Python
Hash chain I wanted to avoid (1)
I tried to move the ball
I tried to estimate the interval.
I tried to describe the traffic in real time with WebSocket
I tried to solve the ant book beginner's edition with python
I want to know the weather with LINE bot feat.Heroku + Python
I tried to automate the watering of the planter with Raspberry Pi
I wanted to create a smart presentation with Jupyter Notebook + nbpresent
[Introduction to StyleGAN] I played with "The Life of a Man" ♬
I want to output the beginning of the next month with Python
I tried to process the image in "sketch style" with OpenCV
I wanted to challenge the classification of CIFAR-10 using Chainer's trainer
[Introduction to sinGAN-Tensorflow] I played with the super-resolution "Challenge Big Imayuyu" ♬
I tried to get started with Bitcoin Systre on the weekend
I tried to process the image in "pencil style" with OpenCV
I tried to expand the size of the logical volume with LVM
For the time being, I want to convert files with ffmpeg !!
I want to check the position of my face with OpenCV!
I tried to improve the efficiency of daily work with Python