2017-08-29 59 views
0

我想制作一个绘制Sierpinsky三角形(任何模)的程序。为了做到这一点,我使用了TkInter。该程序通过随机移动一个点来生成分形,并始终保持在两侧。重复该过程多次后,出现分形。TkInter python - 在画布上创建点以获得Sierpinsky三角形

但是,有一个问题。我不知道如何在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() 

回答

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() 
+0

当你说:“如果你只为图像的每一行调用put方法,你可以获得戏剧性的加速。”? –

+0

@MartínGómez我的意思是说,使用一个像素的数据调用'put'100次比使用100个像素的数据调用'put' 1次要慢得多。 –

0

您可以使用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个10万点的深度,这给:

enter image description here

+1

该解决方案有一个问题:它们通过这样做,真的是2像素×2像素的正方形产生的椭圆形。似乎没有制作像素的方法。 –

+0

IDK,在(x,y,x,y)边界框中的“圆圈”在mac(而不是视网膜)LCD显示器上对我来说为1x1 ...而在(x,y,x + 1 ,y + 1)BB看起来更大......也许它取决于系统? –

0

终于找到一个解决方案:如果一个1x1的点要被放置在像素(x,y)的,它不它E中的命令Xactly公司是:

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

椭圆形的是2×2分的好主意。

原始程序的一个显着特点是,如果每个点被视为一个独立的对象,它会使用大量的RAM。