用户:
小小小嘟嘟查看:1 回复:2 评论:1 创建时间:2022-08-01T12:42:25
【作品展示】

【作品介绍】
【作品说明】:此程序可以模拟牛顿分形。
收敛的点用对应颜色着色(红绿蓝),不收敛的根用灰色着色。
牛顿分形的原理的视频链接附在代码末尾的注释。
【使用方法】:
①鼠标移到一个根并按下鼠标左键拖动,可拖动根,拖动时自动降低分辨率保证流畅,放开鼠标以高分辨率刷新
②点击上下调节迭代次数,点击左右调节放大倍数,点击f将中心移动到鼠标所在位置,点击h调整回初始视角,点击空格(回车)以低(高)分辨率刷新。
请在海龟编辑器上运行此程序,在库管理安装需要安装的库。
(由于gif是在笔记本电脑上录制的,所以很卡)
【作品源代码】
import numpy as np
import pygame, sys
print()
Iter = 20 # iterations
roots = np.array([1.0+0.0j, -0.5+0.8660254037844386j, -0.5-0.8660254037844386j], dtype=complex)
def f(x):
a, b, c = x-roots[0], x-roots[1], x-roots[2]
return x-a*b*c/(a*b+b*c+c*a)
def get_z(x):
for i in range(Iter):
x = f(x)
return x
def get_index():
x0 = np.resize(np.linspace(-focus, focus, pl), (pl, pl))
x0 = x0+x0.transpose()*1j+middle # initial values
z = get_z(x0) # calculate limities
# calculate colors
zc = np.zeros(shape=(pl, pl, 3), dtype='u1')
npsum = np.sum
for i in range(pl):
for j in range(pl):
w = 1/(abs(roots-z[i][j])+0.000001)
zc[i][j] = 256*w/npsum(w)-1
return zc
pygame.init()
rslt = 200 # resolution
middle = 0.0+0.0j
focus = 2
pl = 2*rslt+1 # real and imaginary part len
size = 200
d = size/rslt
screen = pygame.display.set_mode((2*size, 2*size))
def render(zc):
for j in range(pl):
for i in range(pl):
pygame.draw.rect(screen, zc[i][j], (j*d, 2*size-i*d, d, d), 0)
pygame.display.update()
button_size = 7
def draw_button(touched_index=-1):
i = 0
for pos in (roots_cpos-size/focus*middle.conjugate()):
pygame.draw.circle(screen, (255, 255, 255), (pos.real, pos.imag), button_size, 2)
i += 1
pygame.display.update()
print('roots = {}, focus = {}, middle = {}'.format(roots, focus, middle)+' '*15, end='\r')
def roots_trans(cpos):
trans1 = cpos/size
return focus*((trans1.real-1)+(-trans1.imag+1)*1j)
def roots_invtrans(cpos):
trans1 = cpos/focus
return size*(((1+trans1.real)+(1-trans1.imag)*1j))
roots_cpos = roots_invtrans(roots)
def check_pos(cpos):
is_touch_buttons = (abs(roots_cpos-size/focus*middle.conjugate()-cpos) <= 2*button_size)
for i in range(3):
if is_touch_buttons[i]:
return i
return -1
def set_rslt(val):
global rslt, pl, d
rslt = val
pl = 2*rslt+1
d = size/rslt
render(get_index())
draw_button()
down = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
set_rslt(200)
render(get_index())
draw_button()
elif event.key == pygame.K_UP:
if Iter <= 50:
Iter += 1
elif event.key == pygame.K_DOWN:
if Iter > 0:
Iter -= 1
elif event.key == pygame.K_LEFT:
focus *= np.sqrt(2)
roots_cpos = roots_invtrans(roots)
elif event.key == pygame.K_RIGHT:
focus /= np.sqrt(2)
roots_cpos = roots_invtrans(roots)
elif event.key == pygame.K_f:
middle += (cpos.conjugate()/size-1+1j)*focus
middle = np.around(middle.real, 9)+np.around(middle.imag, 9)*1j
elif event.key == pygame.K_h:
focus, middle = 2, 0.0+0.0j
roots_cpos = roots_invtrans(roots)
elif event.key == pygame.K_RETURN:
set_rslt(200)
render(get_index())
draw_button()
elif event.key == pygame.K_SPACE:
set_rslt(50)
render(get_index())
draw_button()
elif event.type == pygame.MOUSEBUTTONUP:
down = 0
set_rslt(200)
render(get_index())
draw_button()
elif event.type == pygame.MOUSEBUTTONDOWN:
down = 1
set_rslt(50)
break
x, y = pygame.mouse.get_pos()
cpos = complex(x, y)
if down == 0:
index = check_pos(cpos)
else:
if index != -1:
roots_cpos[index] = cpos
roots[index] = roots_trans(cpos)
render(get_index())
draw_button()
# 相关视频 https://www.bilibili.com/video/BV1HQ4y1q78v?spm_id_from=333.337.search-card.all.click
# 类似程喵lessons/newtons-fractal
【提示】
部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:
https://python.codemao.cn