Sentaro様から「面白いモノはナーイ ?」との事で、fx-CG50 upython をしばき倒す(?) 「Pickovers' Biomorph」のコードを動かしてみました。
当方が、Pickovers' Biomorph を知った、そのネタ元と言いますと、昔、図書館で読んだ、日経サイエンス誌の連載「コンピューター・リクリエーション」(A. K. Dewdney) なのですが、Pickover biomorphs で検索すると、およその所が解ると思います。
Mandelbrot set graphics の作業の様ですが、少し異なる部分もあります。
詳細はコードをご参照ください。
Pickovers' Biomorphs の場合、繰り返す計算式を色々と変更する事で、描かれる画像が多様に変化します。
このコードでは、
z = z*z+c
を繰り返しますが、これを、例えばつぎの行にある様に、
z = cmath.sin(z*z)-c
とかに変更すると、画像が大きく変化するのです。
複素数平面の座標値に数式を繰り返し適用するため、複素数を扱う関数が必要になりますが、残念ながら、fx-CG50 には cmath module が用意されておりません。
そこで、急ごしらえで cmath module を用意しました。 残念ながら、asin() などはまだ、用意できておりませんが、チョット遊ぶなら、この辺りから始めても十分であると思います。
実行は、プログラムを読み込んだ後、
biom()
と入力する事で実行されます。
ループ中の数式を変更する事でも、画像が大きく変化するのですが、定数 c を変える事でも、微妙に画像が変化します。
定数 c も複素数ですが、biom(c.real, c.imag) の様に、実部と虚部をカンマで分けて指定する事で与えられます。
残念ながら、cmath module が system binary ではなく、実行速度が大変遅いという哀しい部分はありますが、
じわじわとグラフィクスが描かれる様を眺めるのも、手のひらで動く電卓ならではの愉しみであると思います。
追記 on 2024-10-05
過日、K 様にコメント戴き、sqrt() を更新いたしました。
math.copysign() が fx-CG50 には無いため、自家製の copysign() もどき csign() を付け足しましたヨ。これにより、計算速度が向上したという具合には行きませんが、ネタとしては色々と面白かったので、後日、別記したく思います。
謝謝 !
リスト biom.py
# title : biom.py - Pickovers' Biomorph for fx-CG50
# begin : 2024-09-28 19:33:39
from casioplot import *
import math
import cmath
def biom(re=0, im=0) :
width = 383
height = 191
xs=-3.8
xe= 3.8
ys=-1.9
ye= 1.9
c = re - im*1j
# Biomorph
for j in range(height):
for i in range(width):
z = (i*(xe-xs)/width +xs) + 1j*(j*(ys-ye)/height+ye)
# repeating core
k = 0
while abs(z) <= 10 and k < 10:
z = z*z+c
#z = cmath.sin(z*z)-c
k=k+1
#
if abs(z.real) < 10 or abs(z.imag) < 10 :
set_pixel(int(i), int(j))
# show graphix progressively
show_screen()
リスト cmath.py
## title : [WIP] cmath module for fx-CG50
## begin : 2024-09-28 00:38
import math
# copysign() like something ...
def csign(x, y) :
if y == 0.0 :
if str(y) == '-0.0' :
return -abs(x)
else :
return abs(x)
else :
if y < 0 :
return -abs(x)
else :
return abs(x)
#
def phase(x) :
return math.atan2(x.imag, x.real)
##
def exp(x) :
return pow(math.e, x)
##
def ln(x) :
return math.log(abs(x)) + phase(x)*1j
##
def log(x, base=math.e) :
return ln(x) / ln(base)
## thanks K sama ! on 2024-10-04
def sqrt(x) :
# return pow(x, 0.5)
return math.sqrt((abs(z)+z.real)/2) + 1j* csign(math.sqrt((abs(z)-z.real)/2), z.imag)
##
def sin(c) :
return math.sin(c.real)*math.cosh(c.imag) + (math.cos(c.real)*math.sinh(c.imag))*1j
##
def cos(c) :
return math.cos(c.real)*math.cosh(c.imag) - (math.sin(c.real)*math.sinh(c.imag))*1j
##
def tan(c) :
return sin(c) / cos(c)