Last active
February 12, 2020 16:46
Star
You must be signed in to star a gist
Visual representation of the Mandelbrot set in SWI Prolog.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% Jonas Boegle - https://github.com/irgendwr | |
:- use_module(library(pce)). | |
% draw(+Width, +Height, +Xoffset, +Yoffset, +Scale) | |
% Draws a mandelbrot set with a given size, x-/y-offset and Scale factor. | |
draw(Width, Height, Xoffset, Yoffset, Scale) :- | |
% create a new display and open it | |
new(Display, window('mhh, lecker Mandelbrot - Jonas @irgendwr :)')), | |
send(Display, size, size(Width, Height)), | |
send(Display, background, colour(white)), | |
send(Display, display, new(_, text('Wird berechnet...')), point(150, 150)), | |
send(Display, open), | |
% create new image | |
new(Img, image(@nil, Width, Height, pixmap)), | |
new(Bmp, bitmap(Img)), | |
send(Display, display, Bmp, point(0, 0)), | |
% draw the object on the display | |
draw_mandelbrot(Img, Width, Height, Xoffset, Yoffset, Scale), | |
send(Bmp, flush), | |
% if desired save the display as .jpg | |
write_ln('Save the graphics (y/n): '), | |
get_single_char(A), | |
put_code(A), nl, | |
( A =:= 121 -> % ascii(y) = 121 | |
( | |
atomic_list_concat([Scale, '_', Xoffset, '_', Yoffset, '_', Width, 'x', Height, '.jpg'], FileName), | |
send(Img, save, FileName, jpeg) | |
); | |
true | |
), | |
% free objects, | |
free(Bmp), | |
free(Img), | |
free(Display), | |
!. | |
% draw_mandelbrot(+Imgage, +Width, +Height, +Xoffset, +Yoffset, +Scale) | |
% Draws a mandelbrot set with a given size, x-/y-offset and Scale factor. | |
draw_mandelbrot(Imgage, Width, Height, Xoffset, Yoffset, Scale) :- | |
% max. number of iterations | |
MaxIterations is 600, | |
MaxI is Width-1, | |
MaxJ is Height-1, | |
% 0 to Size-1 for X | |
forall(between(0, MaxI, I), ( | |
% 0 to Size-1 for Y | |
forall(between(0, MaxJ, J), ( | |
% calculate center, apply Scale factor and offset | |
X is ((I-(Width/2)) / Scale) - Xoffset, | |
Y is ((J-(Height/2)) / Scale) - Yoffset, | |
% calculate iterations | |
calculate(X, Y, 0, 0, MaxIterations, Result), | |
% get colour | |
getRGB(MaxIterations, Result, R,G,B), | |
% set pixel | |
send(Imgage, pixel(I, J, colour(@default, R, G, B))) | |
)) | |
)). | |
calculate(X, Y, ZX, ZY, Iteration, FinalIteration) :- | |
ZX * ZX + ZY * ZY < 4, % could complex number be in mandelbrot set? | |
Iteration > 0, % is iteration lower than max. iteration? | |
!, % don't backtrace | |
% magic calculations | |
Tmp is ZX * ZX - ZY * ZY + X, | |
ZY2 is 2 * ZX * ZY + Y, | |
Iteration2 is Iteration - 1, | |
% continue | |
calculate(X, Y, Tmp, ZY2, Iteration2, FinalIteration). | |
% we've either reached max. iteration (Iteration = 0) | |
% or complex number is not in mandelbrot set (Iteration = how many iterations it took to find out) | |
calculate(_, _, _, _, Iteration, Iteration). | |
% getRGB(+MaxIterations, +Iterations, -R, -G, -B) | |
% returns the RGB colour for a given number of iterations | |
getRGB(MaxIterations, Iterations, R, G, B) :- | |
Hue is Iterations/MaxIterations*360*2, | |
Brightness is (1 - (1/(Iterations+1))) * 0.8, | |
hsv2rgb(Hue, 1, Brightness, R1, G1, B1), | |
R is floor(R1 * 65535), | |
G is floor(G1 * 65535), | |
B is floor(B1 * 65535). | |
% hsv2rgb(?H, ?S, ?B, ?R, ?G, ?B). | |
% Converts between the HSV and RGB colour models. | |
% Either H,S,V or R,B,G should be instantiated. | |
hsv2rgb(_, 0, V, V, V, V). % zero saturation => gray | |
hsv2rgb(H, S, V, R, G, B) :- | |
S \= 0, % saturation is not zero? | |
H2 is (floor(H) mod 360) / 60, % Hue can have 360 degrees, divided by 60 leaves 6 sectors (0-5), | |
I is floor(H2), | |
F is H2 - I, % factorial part of h | |
P is V * (1 - S), | |
Q is V * (1 - S * F), | |
T is V * (1 - S * (1 - F)), | |
hsvSector2rgb(I, V, P, Q, T, R, G, B). | |
% hsvSector2rgb(+I, +V, +P, +Q, +T, -R, -G, -B) | |
hsvSector2rgb(0, V, P, _, T, V, T, P). | |
hsvSector2rgb(1, V, P, Q, _, Q, V, P). | |
hsvSector2rgb(2, V, P, _, T, P, V, T). | |
hsvSector2rgb(3, V, P, Q, _, P, Q, V). | |
hsvSector2rgb(4, V, P, _, T, T, P, V). | |
hsvSector2rgb(5, V, P, Q, _, V, P, Q). | |
:- draw( | |
960, 540, % width/height | |
1.4, % X offset | |
0.0007, % Y offset | |
2000000 % Scale | |
). | |
% :- draw(512,512, 0.75, 0, 200). | |
% :- draw(512,512, 1.4, 0, 500). | |
% :- draw(512,512, 1.4, 0, 1000). | |
% :- draw(512,512, 1.4, 0, 2000). | |
% :- draw(512,512, 1.4, 0, 10000). | |
% :- draw(512,512, 1.4, 0, 20000). | |
% :- draw(512,512, 1.4, 0, 100000). <== | |
% :- draw(512,512, 1.4, 0, 200000). | |
% :- draw(512,512, 1.4, 0.0008, 500000). | |
% :- draw(512,512, 1.4, 0.0008, 500000). | |
% :- draw(512,512, 1.4, 0.0007, 2000000). | |
% high quality (2k 16:9) | |
% draw(3840,, 1.4, 0.0007, 2000000). | |
% draw(3840,2160, 1.4, 0.0007, 5000000). | |
% draw(3840,2160, 1.4, 0.0007, 10000000). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment