TkInter python - 在 canvas 上创建点以获得 Sierpinski 三角形

TkInter python - creating points on a canvas to obtain a Sierpinsky triangle

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

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

是否有在 canvas 上绘制点的函数或其他工具(使用 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()

您可以使用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 个点,这给出:

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

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

椭圆形是 2x2 点的好主意。

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

如果您想绘制像素,canvas 可能是错误的选择。您可以创建 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()