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()
  • 相关阅读:
    团队项目-smart原则
    团队项目-作业管理系统
    团队模式和团队的开发模式是什么,它们有什么关系?
    软件工作量的估计有哪些方法?
    腾讯qq的发展史
    软件过程与项目管理(第二次作业)
    有学生提到,在大学选课的时候,可以写一个“刷课机”的程序,利用学校选课系统的弱点或漏洞,帮助某些人选到某些课程。或者帮助用户刷购票网站,先买到火车票。这些软件合法么?符合道德规范么?是在“软件工程”的研究范围么?
    mysql中explain的type的解释
    php 中类型转换 numfamat、round函数tips
    python client端收不到server端构造的结构体数据
  • 原文地址:https://www.cnblogs.com/RChen/p/pil_bezier.html
Copyright © 2011-2022 走看看