【问题标题】:How to draw polygons with Python?如何用 Python 绘制多边形?
【发布时间】:2017-10-13 18:03:49
【问题描述】:

我有以下格式的 x、y 坐标输入值:

[[1,1], [2,1], [2,2], [1,2], [0.5,1.5]]

我想画多边形,但不知道怎么画!

谢谢

【问题讨论】:

  • 你使用哪个库来绘图?

标签: python tkinter plot polygon tkinter-canvas


【解决方案1】:

使用matplotlib.pyplot

import matplotlib.pyplot as plt

coord = [[1,1], [2,1], [2,2], [1,2], [0.5,1.5]]
coord.append(coord[0]) #repeat the first point to create a 'closed loop'

xs, ys = zip(*coord) #create lists of x and y values

plt.figure()
plt.plot(xs,ys) 
plt.show() # if you need...

【讨论】:

  • 也许您将 plt.show() 添加到您的代码中。否则只是复制粘贴的人什么都看不到
  • 完成。我用的是 Spyder 和plt.show() 不是必须的,所以我没有考虑...
  • 如果多边形是一个矩形,使用matplotlib.patches 添加会更容易/更快,如here 所述
【解决方案2】:

另一种绘制多边形的方法是:

import PIL.ImageDraw as ImageDraw
import PIL.Image as Image

image = Image.new("RGB", (640, 480))

draw = ImageDraw.Draw(image)

# points = ((1,1), (2,1), (2,2), (1,2), (0.5,1.5))
points = ((100, 100), (200, 100), (200, 200), (100, 200), (50, 150))
draw.polygon((points), fill=200)

image.show()

请注意,您需要安装枕头库。此外,我将您的坐标放大了 100 倍,以便我们可以在 640 x 480 的屏幕上看到多边形。

希望这会有所帮助。

【讨论】:

    【解决方案3】:
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.patches import Polygon
    
    y = np.array([[1,1], [2,1], [2,2], [1,2], [0.5,1.5]])
    
    p = Polygon(y, facecolor = 'k')
    
    fig,ax = plt.subplots()
    
    ax.add_patch(p)
    ax.set_xlim([0,3])
    ax.set_ylim([0,3])
    plt.show()
    

    【讨论】:

      【解决方案4】:

      另外,如果你在窗口上绘图,使用这个:

      dots = [[1,1], [2,1], [2,2], [1,2], [0.5,1.5]]
      from tkinter import Canvas
      c = Canvas(width=750, height=750)
      c.pack()
      out = []
      for x,y in dots:
          out += [x*250, y*250]
      c.create_polygon(*out, fill='#aaffff')#fill with any color html or name you want, like fill='blue'
      c.update()
      

      或者你也可以使用这个:

      dots = [[1,1], [2,1], [2,2], [1,2], [0.5,1.5]]
      out = []
      for x,y in dots:
          out.append([x*250, y*250])
      import pygame, sys
      from pygame.locals import *
      pygame.init()
      DISPLAYSURF = pygame.display.set_mode((750, 750), 0, 32)
      pygame.display.set_caption('WindowName')
      DISPLAYSURF.fill((255,255,255))#< ; \/ - colours
      pygame.draw.polygon(DISPLAYSURF, (0, 255,0), out)
      while True:
          for event in pygame.event.get():
              if event.type == QUIT:
                  pygame.quit()
                  sys.exit()
          pygame.display.update()
      

      首先需要tkinter,其次需要pygame。第一个加载速度更快,第二个绘制速度更快,如果您将 DISPLAYSURF.fillpygame.draw.polygon 的坐标稍有不同放入循环中,它将比 tkinter 中的相同内容更好。因此,如果您的多边形正在飞行和弹跳,请使用第二个,但如果它只是稳定的东西,请先使用。另外,在 python2 中使用from Tkinter,而不是from tkinter。 我已经在 raspberrypi3 上检查过这段代码,它可以工作。

      ------------编辑------------

      关于 PIL 和 PYPLOT 方法的更多信息,请参阅另一个答案:

      matplotlib 使用tkinter,也许matplotlib 更容易使用,但它基本上更酷tkinter 窗口。

      PIL在本例中使用imagemagick,这是一个非常好的图像编辑工具

      如果您还需要对图像应用效果,请使用PIL

      如果您需要更难的数学数字,请使用matplotlib.pyplot

      对于动画,使用pygame

      如果您不知道任何更好的方法,请使用tkinter

      tkinter 初始化速度很快。 pygame 更新很快。 pyplot 只是一个几何工具。

      【讨论】:

        【解决方案5】:

        所有其他答案似乎都很高,我想这是我作为机械工程师的印象。这是代码的简单版本:

        from numpy import *
        from matplotlib.pyplot import *
        x = ([1,2,2,1,0.5,1]) 
        y = ([1,1,2,2,1.5,1])
        plot(x,y)
        show()
        

        【讨论】:

        • 不要使用通配符导入。不建议这样做,您可以了解原因。对于像我这样的初学者,我必须用谷歌搜索 plot 是属于 numpy 还是 matplotlib.pyplot。与表演相同。
        【解决方案6】:

        如果你想在代表图像的矩阵上绘制多边形,scikit-image 有 3 个函数供你使用:

        如果您的基准测试结果相反,请纠正我,但我认为这些功能非常快速

        示例

        import numpy as np
        from skimage.draw import polygon2mask, polygon, polygon_perimeter
        
        shape = (10, 10)  # image shape
        points = [(5, -1), (-1, 5), (5, 11), (10, 5)]  # polygon points
        
        imgp2 = polygon2mask(shape, points).astype(str)  # astype() converts bools to strings
        imgp2[imgp2 == "True"] = "O"
        imgp2[imgp2 == "False"] = "."
        
        imgp = np.full(shape, ".")  # fill a n*d matrix with '.'
        imgpp = imgp.copy()
        points = np.transpose(points)  # change format to ([5, -1, 5, 10], [-1, 5, 11, 5])
        
        rr, cc = polygon(*points, shape=shape)
        imgp[rr, cc] = "O"
        
        rr, cc = polygon_perimeter(*points, shape=shape, clip=True)
        imgpp[rr, cc] = "O"
        
        print(imgp2, imgp, imgpp, sep="\n\n")
        

        结果:

        [['.' '.' '.' '.' 'O' 'O' '.' '.' '.' '.']
         ['.' '.' '.' 'O' 'O' 'O' 'O' '.' '.' '.']
         ['.' '.' 'O' 'O' 'O' 'O' 'O' 'O' '.' '.']
         ['.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' '.']
         ['O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['.' '.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' '.']
         ['.' '.' '.' 'O' 'O' 'O' 'O' 'O' '.' '.']
         ['.' '.' '.' '.' 'O' 'O' 'O' '.' '.' '.']]
        
        [['.' '.' '.' '.' 'O' 'O' '.' '.' '.' '.']
         ['.' '.' '.' 'O' 'O' 'O' 'O' '.' '.' '.']
         ['.' '.' 'O' 'O' 'O' 'O' 'O' 'O' '.' '.']
         ['.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' '.']
         ['O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O' 'O']
         ['.' '.' 'O' 'O' 'O' 'O' 'O' 'O' 'O' '.']
         ['.' '.' '.' 'O' 'O' 'O' 'O' 'O' '.' '.']
         ['.' '.' '.' '.' 'O' 'O' 'O' '.' '.' '.']]
        
        [['.' '.' '.' '.' 'O' 'O' 'O' '.' '.' '.']
         ['.' '.' '.' 'O' '.' '.' '.' 'O' '.' '.']
         ['.' '.' 'O' '.' '.' '.' '.' '.' 'O' '.']
         ['.' 'O' '.' '.' '.' '.' '.' '.' '.' 'O']
         ['O' '.' '.' '.' '.' '.' '.' '.' '.' 'O']
         ['O' '.' '.' '.' '.' '.' '.' '.' '.' 'O']
         ['O' '.' '.' '.' '.' '.' '.' '.' '.' 'O']
         ['.' 'O' 'O' '.' '.' '.' '.' '.' '.' 'O']
         ['.' '.' '.' 'O' '.' '.' '.' 'O' 'O' '.']
         ['.' '.' '.' '.' 'O' 'O' 'O' '.' '.' '.']]
        

        【讨论】:

          【解决方案7】:

          matplotlib.patches有一个名为Polygon的函数,可以导入为from matplotlib.patches import Polygon。您可以使用轴对象的add_patch 方法绘制多边形。

          from matplotlib.patches import Polygon
          import matplotlib.pyplot as plt
          
          polygon1 = Polygon([(0,5), (1,1), (3,0),])
          
          fig, ax = plt.subplots(1,1)
          
          ax.add_patch(polygon1)
          
          plt.ylim(0,6)
          plt.xlim(0,6)
          

          【讨论】:

            【解决方案8】:

            这是一个单行(假设您已导入 matplotlib.pyplot 并定义了您的多边形 - 如果没有,那么它是三行^^):

            import matplotlib.pyplot as plt
            poly = [[1,1], [2,1], [2,2], [1,2], [0.5,1.5]]
            
            plt.plot(*np.column_stack(poly+[poly[0]]));
            

            【讨论】:

              【解决方案9】:

              尽管有很多答案,这里是我使用 Turtle 模块的方法。 turtle 模块以面向对象和面向过程的方式提供海龟图形原语。

              import turtle
                
              
              t = turtle.Turtle()
                
              # input for number of sides 
              n_sides = int(input("Enter the sides of the polygon : "))
                
              # length of the polygon
              l_sides = int(input("Enter the length of the polygon : "))
                
                
              for _ in range(n_sides):
                  turtle.fd(l_sides)
                  turtle.rt(360 / n_sides)
              

              【讨论】:

                【解决方案10】:

                tkinter 画布非常强大,可以轻松绘制各种多边形,并具有许多可操作的内置属性:

                示例(截图):

                示例代码:

                import tkinter as tk
                
                
                def _scale_and_flip(point, offset):
                    """
                    scales the provided point and flips the y axis so it points upwards
                    origin (0, 0) at the bottom left corner of the screen
                    returns the point scaled and flipped
                    """
                    x, y = point
                    ox, oy = offset
                    return ((x+ox) * SCALE, HEIGHT - (y+oy) * SCALE)
                
                def scale_and_flip(polygon, offset=(0, 0)):
                    """
                    scales the provided point and flips the y axis so it points upwards
                    origin (0, 0) at the bottom left corner of the screen
                    returns a sequence of scaled and flipped points representing the polygon ready to render
                    """
                    return [_scale_and_flip(point, offset) for point in polygon]
                
                
                if __name__ == '__main__':
                    WIDTH, HEIGHT = 500, 500
                    SCALE = 100
                    polygon_points = [[1, 1], [2, 1], [2, 2], [1, 2], [0.5, 1.5]]
                
                    root = tk.Tk()
                    canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg='cyan')
                    canvas.pack()
                
                    canvas.create_polygon(scale_and_flip(polygon_points), fill='beige', outline='black')
                    canvas.create_polygon(scale_and_flip(polygon_points, (0, 2)), fill='beige', outline='black', smooth=True)
                    canvas.create_polygon(scale_and_flip(polygon_points, (2, 0)), fill='beige', outline='black', dash=(1, 3))
                    canvas.create_polygon(scale_and_flip(polygon_points, (2, 2)), fill='beige', outline='black', dash=(1, 3), smooth=True)
                
                    root.mainloop()
                

                更多tk.Canvas.create_polygon选项和属性可以找到here

                【讨论】:

                  猜你喜欢
                  • 2011-01-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-03-03
                  • 2011-12-30
                  • 2010-09-26
                  • 2011-01-04
                  相关资源
                  最近更新 更多