@villares @solub @tabreturn Jörg Kantel has been at it again on his blog, I picked up his NewtonFractal sketch and translated it for JRubyArt here:-
# frozen_string_literal: true
IMGX = 512
IMGY = 512
MAXIT = 20 # max iterations allowed
EPS = 1e-3 # max error allowed
COMPLEX = Complex(1e-6, 1e-6) # step increment
attr_reader :xa, :xb, :ya, :yb, :z
def settings
size(IMGX, IMGY)
end
def setup
sketch_title 'Newton Fractal'
color_mode(HSB)
# Drawing area
@xa = -1.0
@xb = 1.0
@ya = -1.0
@yb = 1.0
no_loop
end
def draw
load_pixels
grid(IMGY, IMGX) do |y, x|
zy = y * (yb - ya) / (IMGY - 1) + ya
zx = x * (xb - xa) / (IMGX - 1) + xa
@z = Complex(zx, zy)
(0...MAXIT).each do |i|
# Newton iteration
z0 = z - func(z) / ((func(z + COMPLEX) - func(z)) / COMPLEX)
break if (z0 - z).abs < EPS
@z = z0
# pixels[x + y * width] = color(i % 5 * 64, i % 17 * 16, i % 9 * 32)
pixels[x + y * width] = color(i%5*64, i%9*32, i%17*16)
end
end
update_pixels
end
def func(z)
# z**3 - 1.0
z**4 - 1.0
end
Here is what his suggested variation looks like:-
7 Likes
In principle you can explore any number of roots of unity eg z**8
:-
Here I’ve expanded the drawing area to
-2 to 2
get a wider perspective.
1 Like
Then if you substitute for some other funky cubic function there is this:-
Or this view:-
2 Likes
Thank you so much @monkstone! It is lovely!
# from https://discourse.processing.org/t/newton-fractal-sketch/24211
IMGX = 512
IMGY = 512
MAXIT = 20 # max iterations allowed
EPS = 1e-3 # max error allowed, could use Processing's EPSILON constant
COMPLEX = complex(1e-6, 1e-6) # step increment
def settings():
size(IMGX, IMGY)
def setup():
global xa, xb, ya, yb
this.surface.setTitle('Newton Fractal')
colorMode(HSB)
# Drawing area
xa = -1.0
xb = 1.0
ya = -1.0
yb = 1.0
noLoop()
def draw():
loadPixels()
for y in range(IMGY):
for x in range(IMGX):
zy = y * (yb - ya) / (IMGY - 1) + ya
zx = x * (xb - xa) / (IMGX - 1) + xa
z = complex(zx, zy)
for i in range(MAXIT):
# Newton iteration
z0 = z - func(z) / ((func(z + COMPLEX) - func(z)) / COMPLEX)
if abs(z0 - z) < EPS:
break
z = z0
# pixels[x + y * width] = color(i % 5 * 64, i % 17 * 16, i % 9 * 32)
pixels[x + y * width] = color(i %
5 * 64, i % 9 * 32, i % 17 * 16)
updatePixels()
def func(z):
# return z**3 - 1.0
return z ** 4 - 1.0
1 Like
Here’s another variation with a complex polynomial function (ie 4+3i
):-
Or this with
-0.5+3
:-
2 Likes
In this sketch I take advantage of the built in support for complex numbers in ruby. But this got me thinking that I’ve yet to take advantage of ruby refinements (a different sort of monkey patching that does not pollute global namespace. I reasoned that it might be quite interesting to explore refinements with the Vec2D class see my recent blog entry. This is akin to vec2 glsl code in my droste.glsl.
1 Like