zoukankan      html  css  js  c++  java
  • 用 PIL 绘制二次贝塞尔曲线

    PIL(Python Image Library) 中有 line, ellipse, rectangle 等常规绘图的函数,但缺少绘制曲线的函数,今天我的需求中需要绘制一个二次贝塞尔曲线(两个端点,一个控制点)。无奈之下,到网上找了一个 c 语言写的算法,把它写成了 python 的,并且写成了类的形式。

    #coding=utf-8
    #
     二次贝塞尔曲线绘图程序
    #
     木野狐(Neil Chen) http://rchen.cnblogs.com
    #
     2007-5-16
    #
     根据 c 程序改写为 python 类的形式,参考:
    #
     http://hi.baidu.com/sunyante/blog/item/2627d911b3061810b8127b70.html

    from math import sqrt
    import Image, ImageDraw

    class Bezier2(object):
        
    def __init__(self, draw, points, line_width, line_color):
            self.draw 
    = draw
            self.points 
    = points
            self.line_width 
    = line_width
            self.line_color 
    = line_color
            self.current_point 
    = (0, 0)

        
    def moveto(self, p):
            self.current_point 
    = p
        
        
    def lineto(self, p):
            self.draw.line((self.current_point, p), width
    =self.line_width, fill=self.line_color)
            self.current_point 
    = p

        
    def render(self):
            NO 
    = 3
            KT 
    = 5
            m 
    = NO - 1
            p 
    = {} # p[3][2]
            for i in range(0, NO, 2):
                p[i] 
    = self.points[i]
            
            l1 
    = 1.0 * (self.points[0][0] - self.points[1][0])
            ll 
    = 1.0 * (self.points[0][1- self.points[1][1])
            l1 
    = sqrt(l1 * l1 + ll * ll)
            
            l2 
    = 1.0 * (self.points[2][0] - self.points[1][0])
            ll 
    = 1.0 * (self.points[2][1- self.points[1][1])
            l2 
    = sqrt(l2 * l2 + ll * ll)
            
            p[
    1= (
                ((l1 
    + l2) * (l1 + l2) * self.points[1][0] - l2 * l2 * self.points[0][0] - l1 * l1 * self.points[2][0]) / (2 * l1 * l2),
                ((l1 
    + l2) * (l1 + l2) * self.points[1][1- l2 * l2 * self.points[0][1- l1 * l1 * self.points[2][1]) / (2 * l1 * l2)
            )
            
    '''
            # 画出切线
            self.moveto(p[0])
            for i in range(1, m+1):
                self.lineto(p[i])
            
    '''
            
            pk 
    = {}  # pk[129][2]
            for i in range(m + 1):
                pk[i] 
    = p[i]
            
            pt 
    = {} # pt[129][2]
            for k in range(KT + 1):
                
    for i in range(0, m + 12):
                    pt[
    2*i] = pk[i]
                
    for i in range(m):
                    pt[
    2*+ 1= (
                        int(pk[i][0] 
    + pk[i+1][0]) >> 1,
                        int(pk[i][
    1+ pk[i+1][1]) >> 1
                    )
                
    for i in range(1, m):
                    pt[
    2*i] = (
                        int(pt[
    2*i-1][0] + pt[2*i+1][0]) >> 1,
                        int(pt[
    2*i-1][1+ pt[2*i+1][1]) >> 1
                    )
                
    for i in range(2*+ 1):
                    pk[i] 
    = pt[i]
                
                
    if k == KT:
                    
    break
                m 
    <<= 1
            self.moveto(pk[0])
            
    for i in range(12*+ 1):
                self.lineto(pk[i])

    # 测试代码
    if __name__ == '__main__':
        im 
    = Image.new('RGBA', (1024,1024), (255,255,255))
        draw 
    = ImageDraw.Draw(im)

        points 
    = ((150,300), (300,200), (485,300))
        b 
    = Bezier2(draw, points, 1, (0,0,255))
        b.render()
        
        points2 
    = ((150,300), (100,400), (485,300))
        b2 
    = Bezier2(draw, points2, 3, (0,255,0))
        b2.render()
        
        
    del draw
        im.show()
  • 相关阅读:
    React antd的select框的onchange事件 只能点击一次 如果想选中的值 还可以被点击 就用onselect事件
    formatTime.js
    typeScript
    React react-router在url参数不同的情况下跳转页面不更新
    React 组件
    三、猜字符小游戏
    二、Java学习之方法
    Java学习之数组
    JavaWeb的学习--第五天 javascript03
    JavaWeb的学习--第四天 javascript02
  • 原文地址:https://www.cnblogs.com/RChen/p/pil_bezier.html
Copyright © 2011-2022 走看看