【问题标题】:TkInter python - creating points on a canvas to obtain a Sierpinsky triangleTkInter python - 在画布上创建点以获得谢尔宾斯基三角形
【发布时间】:2018-02-07 04:59:18
【问题描述】:

我想制作一个绘制谢尔宾斯基三角形(任何模数)的程序。为了做到这一点,我使用了 TkInter。该程序通过随机移动一个点来生成分形,始终将其保持在侧面。多次重复这个过程后,分形就出现了。

但是,有一个问题。我不知道如何在 TkInter 的画布上绘制点。程序的其余部分还可以,但我不得不“作弊”以便通过绘制小线而不是点来绘制点。它或多或少地工作,但它没有尽可能多的分辨率。

是否有在画布上绘制点的功能,或其他工具(使用 Python)?也欢迎改进程序其余部分的想法。

谢谢。这是我所拥有的:

from tkinter import *
import random
import math
def plotpoint(x, y):
    global canvas
    point = canvas.create_line(x-1, y-1, x+1, y+1, fill = "#000000")
x = 0 #Initial coordinates
y = 0
#x and y will always be in the interval [0, 1]
mod = int(input("What is the modulo of the Sierpinsky triangle that you want to generate? "))
points = int(input("How many points do you want the triangle to have? "))
tkengine = Tk() #Window in which the triangle will be generated
window = Frame(tkengine)
window.pack()
canvas = Canvas(window, height = 700, width = 808, bg = "#FFFFFF") #The dimensions of the canvas make the triangle look equilateral
canvas.pack()
for t in range(points):
    #Procedure for placing the points
    while True:
        #First, randomly choose one of the mod(mod+1)/2 triangles of the first step. a and b are two vectors which point to the chosen triangle. a goes one triangle to the right and b one up-right. The algorithm gives the same probability to every triangle, although it's not efficient.
        a = random.randint(0,mod-1)
        b = random.randint(0,mod-1)
        if a + b < mod:
            break
    #The previous point is dilated towards the origin of coordinates so that the big triangle of step 0 becomes the small one at the bottom-left of step one (divide by modulus). Then the vectors are added in order to move the point to the same place in another triangle.
    x = x / mod + a / mod + b / 2 / mod
    y = y / mod + b / mod
    #Coordinates [0,1] converted to pixels, for plotting in the canvas.
    X = math.floor(x * 808)
    Y = math.floor((1-y) * 700)
    plotpoint(X, Y)
tkengine.mainloop()

【问题讨论】:

    标签: python-3.x tkinter tkinter-canvas


    【解决方案1】:

    如果您想绘制像素,画布可能是错误的选择。您可以创建PhotoImage 并修改单个像素。如果你绘制每个单独的像素会有点慢,但是如果你只为图像的每一行调用一次put 方法,你可以获得显着的加速。

    这是一个完整的例子:

    from tkinter import *
    import random
    import math
    
    def plotpoint(x, y):
        global the_image
        the_image.put(('#000000',), to=(x,y))
    
    x = 0
    y = 0
    mod = 3
    points = 100000
    tkengine = Tk() #Window in which the triangle will be generated
    window = Frame(tkengine)
    window.pack()
    the_image = PhotoImage(width=809, height=700)
    label = Label(window, image=the_image, borderwidth=2, relief="raised")
    label.pack(fill="both", expand=True)
    
    for t in range(points):
        while True:
            a = random.randint(0,mod-1)
            b = random.randint(0,mod-1)
            if a + b < mod:
                break
        x = x / mod + a / mod + b / 2 / mod
        y = y / mod + b / mod
    
        X = math.floor(x * 808)
        Y = math.floor((1-y) * 700)
        plotpoint(X, Y)
    
    tkengine.mainloop()
    

    【讨论】:

    • 当你说:“如果你只为图像的每一行调用一次 put 方法,你可以获得显着的加速。”是什么意思?
    • @MartínGómez 我的意思是用一个像素的数据调用put 100 次比用100 个像素的数据调用put 1 次要慢得多。
    【解决方案2】:

    您可以使用canvas.create_oval 与边界框的两个角相同的坐标:

    from tkinter import *
    import random
    import math
    def plotpoint(x, y):
        global canvas
    #     point = canvas.create_line(x-1, y-1, x+1, y+1, fill = "#000000")
        point = canvas.create_oval(x, y, x, y, fill="#000000", outline="#000000")
    x = 0 #Initial coordinates
    y = 0
    #x and y will always be in the interval [0, 1]
    mod = int(input("What is the modulo of the Sierpinsky triangle that you want to generate? "))
    points = int(input("How many points do you want the triangle to have? "))
    tkengine = Tk() #Window in which the triangle will be generated
    window = Frame(tkengine)
    window.pack()
    canvas = Canvas(window, height = 700, width = 808, bg = "#FFFFFF") #The dimensions of the canvas make the triangle look equilateral
    canvas.pack()
    for t in range(points):
        #Procedure for placing the points
        while True:
            #First, randomly choose one of the mod(mod+1)/2 triangles of the first step. a and b are two vectors which point to the chosen triangle. a goes one triangle to the right and b one up-right. The algorithm gives the same probability to every triangle, although it's not efficient.
            a = random.randint(0,mod-1)
            b = random.randint(0,mod-1)
            if a + b < mod:
                break
        #The previous point is dilated towards the origin of coordinates so that the big triangle of step 0 becomes the small one at the bottom-left of step one (divide by modulus). Then the vectors are added in order to move the point to the same place in another triangle.
        x = x / mod + a / mod + b / 2 / mod
        y = y / mod + b / mod
        #Coordinates [0,1] converted to pixels, for plotting in the canvas.
        X = math.floor(x * 808)
        Y = math.floor((1-y) * 700)
        plotpoint(X, Y)
    tkengine.mainloop()
    

    深度为 3 和 100,000 点,这给出:

    【讨论】:

    • 这个解决方案还有一个问题:这样做生成的椭圆实际上是 2 px x 2 px 正方形。似乎没有办法制作像素。
    • IDK,在 (x, y, x, y) 的边界框中,“圆圈”在 mac(不是视网膜)LCD 显示器上对我来说是 1x1 ......而 ( x, y, x+1, y+1) BB 看起来更大……也许这取决于系统?
    【解决方案3】:

    终于找到了一个解决方案:如果要在像素 (x,y) 中放置一个 1x1 点,则执行此操作的命令完全正确是:

    point = canvas.create_line(x, y, x+1, y+1, fill = "colour")

    椭圆形适合 2x2 点。

    原始程序的显着之处在于,如果将每个点都视为一个单独的对象,它会使用大量 RAM。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      相关资源
      最近更新 更多