2017-08-29 96 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。