Julia set: Difference between revisions
m (→{{header|REXX}}: added a comment in the output section.) |
No edit summary |
||
Line 712: | Line 712: | ||
bitmap.show()</lang> |
bitmap.show()</lang> |
||
=={{header|Racket}}== |
|||
[[File:JuliaSet_racket.png|250px|thumb|right]] |
|||
<lang racket> |
|||
;; Based on Mandelbrot code (GPL) from: |
|||
;; https://github.com/hebr3/Mandelbrot-Set-Racket/blob/master/Mandelbrot.v6.rkt |
|||
;; Julia set algoithm (and coloring) from: |
|||
;; http://lodev.org/cgtutor/juliamandelbrot.html |
|||
;; HSV code (GPL) based on: |
|||
;; https://github.com/takikawa/pict-utils/blob/master/pict-utils/hsv.rkt |
|||
#lang racket |
|||
;; Required to generate image |
|||
(require picturing-programs) |
|||
;; CONSTANTS - NUMBERS |
|||
(define DEPTH 300) |
|||
(define WIDTH 800) |
|||
(define HEIGHT 600) |
|||
;; Structures |
|||
(struct posn [x y] #:transparent) |
|||
;; CONSTANTS - GRAPHIC |
|||
(define BACKGROUND (rectangle WIDTH HEIGHT 'solid 'grey)) |
|||
(define jcnst (posn -0.7 0.27015)) |
|||
;; PROCEDURES |
|||
;; make an RGB color from HSV values |
|||
(define (make-color/hsv hue saturation value) |
|||
(define chroma (* saturation value)) |
|||
(define hue* (/ (remainder* hue (* 2 pi)) (/ pi 3))) |
|||
(define X (* chroma (- 1 (abs (- (remainder* hue* 2) 1))))) |
|||
(define-values (r1 g1 b1) |
|||
(cond [(and (<= 0 hue*) (< hue* 1)) (values chroma X 0)] |
|||
[(and (<= 1 hue*) (< hue* 2)) (values X chroma 0)] |
|||
[(and (<= 2 hue*) (< hue* 3)) (values 0 chroma X)] |
|||
[(and (<= 3 hue*) (< hue* 4)) (values 0 X chroma)] |
|||
[(and (<= 4 hue*) (< hue* 5)) (values X 0 chroma)] |
|||
[(and (<= 5 hue*) (< hue* 6)) (values chroma 0 X)])) |
|||
(define m (- value chroma)) |
|||
(apply make-color (map (λ (x) (exact-round (* 255 (+ x m)))) |
|||
(list r1 g1 b1)))) |
|||
;; general remainder |
|||
(define (remainder* n1 n2) |
|||
(define num-divides (/ n1 n2)) |
|||
(- n1 (* (floor num-divides) n2))) |
|||
;; Posn -> Number |
|||
;; Returns the magnitude of the posn |
|||
(define (posn-mag pt) |
|||
(let ([pt-x (posn-x pt)] |
|||
[pt-y (posn-y pt)]) |
|||
(sqrt (+ (* pt-x pt-x) |
|||
(* pt-y pt-y))))) |
|||
;; Posn Posn -> Posn |
|||
;; Posn addition |
|||
(define (posn+ pt1 pt2) |
|||
(let ([pt1-x (posn-x pt1)] |
|||
[pt1-y (posn-y pt1)] |
|||
[pt2-x (posn-x pt2)] |
|||
[pt2-y (posn-y pt2)]) |
|||
(posn (+ pt1-x pt2-x) |
|||
(+ pt1-y pt2-y)))) |
|||
;; Posn Posn -> Posn |
|||
;; Posn multiplication |
|||
(define (posn* pt1 pt2) |
|||
(let ([x1 (posn-x pt1)] |
|||
[y1 (posn-y pt1)] |
|||
[x2 (posn-x pt2)] |
|||
[y2 (posn-y pt2)]) |
|||
(posn (- (* x1 x2) (* y1 y2)) |
|||
(+ (* x1 y2) (* x2 y1))))) |
|||
;; Posn -> Posn |
|||
;; Posn square |
|||
(define (posn-sqr pt) |
|||
(posn* pt pt)) |
|||
;; Posn -> Number |
|||
;; Returns the julia set escape number for a given complex number |
|||
;; given in rectangular coordinates. |
|||
(define (julia-set-number start) |
|||
(define (iter result count) |
|||
(cond [(> (posn-mag result) 2) (sub1 count)] |
|||
[(> count DEPTH) DEPTH] |
|||
[else (iter (posn+ jcnst (posn-sqr result)) |
|||
(add1 count))])) |
|||
(iter start 1)) |
|||
;; Number -> Number |
|||
;; Returns the scaled location of a point |
|||
(define (scaled-x x) |
|||
(/ (* 1.5 (- x (/ WIDTH 2))) (* 0.5 WIDTH))) |
|||
(define (scaled-y y) |
|||
(/ (- y (/ HEIGHT 2)) (* 0.5 HEIGHT))) |
|||
;; Generates image |
|||
(define M-Image |
|||
(map-image |
|||
(λ (x y c) |
|||
(let* ([ref (julia-set-number (posn (scaled-x x) (scaled-y y)))]) |
|||
(cond [(= ref DEPTH) (name->color 'black)] |
|||
[else (make-color/hsv (* 2 (* pi (/ ref DEPTH))) 1 1)]) )) |
|||
BACKGROUND)) |
|||
M-Image ;show image if using drracket |
|||
(save-image M-Image "julias.png") |
|||
</lang> |
|||
=={{header|REXX}}== |
=={{header|REXX}}== |
Revision as of 18:44, 22 December 2016
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Generate and draw a Julia set.
- Related tasks
AWK
<lang AWK>
- syntax: GAWK -f JULIA_SET.AWK [real imaginary]
BEGIN {
c_real = (ARGV[1] != "") ? ARGV[1] : -0.8 c_imaginary = (ARGV[2] != "") ? ARGV[2] : 0.156 printf("%s %s\n",c_real,c_imaginary) for (v=-100; v<=100; v+=10) { for (h=-280; h<=280; h+=10) { x = h / 200 y = v / 100 plot_char = "#" for (i=1; i<=50; i++) { z_real = x * x - y * y + c_real z_imaginary = x * y * 2 + c_imaginary if (z_real ^ 2 > 10000) { plot_char = " " break } x = z_real y = z_imaginary } printf("%1s",plot_char) } printf("\n") } exit(0)
} </lang>
- Output:
-0.8 0.156 # # # # #### #### ###### ######## # ## ######## ## # # ######## ## # ######### # # ##### # # ######## ### ######## # # ### # ## # # #### ##### # ##### # ##### #### # # ## # ### # # ######## ### ######## # # ##### # # ######### # ## ######## # # ## ######## ## # ######## ###### #### #### # # # #
C++
<lang cpp>
- include <windows.h>
- include <string>
- include <complex>
const int BMP_SIZE = 600, ITERATIONS = 512; const long double FCT = 2.85, hFCT = FCT / 2.0;
class myBitmap { public:
myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {} ~myBitmap() { DeleteObject( pen ); DeleteObject( brush ); DeleteDC( hdc ); DeleteObject( bmp ); } bool create( int w, int h ) { BITMAPINFO bi; ZeroMemory( &bi, sizeof( bi ) ); bi.bmiHeader.biSize = sizeof( bi.bmiHeader ); bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biWidth = w; bi.bmiHeader.biHeight = -h; HDC dc = GetDC( GetConsoleWindow() ); bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 ); if( !bmp ) return false; hdc = CreateCompatibleDC( dc ); SelectObject( hdc, bmp ); ReleaseDC( GetConsoleWindow(), dc ); width = w; height = h; return true; } void clear( BYTE clr = 0 ) { memset( pBits, clr, width * height * sizeof( DWORD ) ); } void setBrushColor( DWORD bClr ) { if( brush ) DeleteObject( brush ); brush = CreateSolidBrush( bClr ); SelectObject( hdc, brush ); } void setPenColor( DWORD c ) { clr = c; createPen(); } void setPenWidth( int w ) { wid = w; createPen(); } void saveBitmap( std::string path ) { BITMAPFILEHEADER fileheader; BITMAPINFO infoheader; BITMAP bitmap; DWORD wb; GetObject( bmp, sizeof( bitmap ), &bitmap ); DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight]; ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) ); ZeroMemory( &infoheader, sizeof( BITMAPINFO ) ); ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) ); infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8; infoheader.bmiHeader.biCompression = BI_RGB; infoheader.bmiHeader.biPlanes = 1; infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader ); infoheader.bmiHeader.biHeight = bitmap.bmHeight; infoheader.bmiHeader.biWidth = bitmap.bmWidth; infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ); fileheader.bfType = 0x4D42; fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER ); fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage; GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS ); HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL ); WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL ); WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL ); CloseHandle( file ); delete [] dwpBits; } HDC getDC() const { return hdc; } int getWidth() const { return width; } int getHeight() const { return height; } DWORD* bits() const { return ( DWORD* )pBits; }
private:
void createPen() { if( pen ) DeleteObject( pen ); pen = CreatePen( PS_SOLID, wid, clr ); SelectObject( hdc, pen ); } HBITMAP bmp; HDC hdc; HPEN pen; HBRUSH brush; void *pBits; int width, height, wid; DWORD clr;
}; class julia { public:
void draw( std::complex<long double> k ) { bmp.create( BMP_SIZE, BMP_SIZE ); DWORD* bits = bmp.bits(); int res, pos; std::complex<long double> c, factor( FCT / BMP_SIZE, FCT / BMP_SIZE ) ;
for( int y = 0; y < BMP_SIZE; y++ ) { pos = y * BMP_SIZE;
c.imag( ( factor.imag() * y ) + -hFCT );
for( int x = 0; x < BMP_SIZE; x++ ) { c.real( factor.real() * x + -hFCT ); res = inSet( c, k ); if( res ) { int n_res = res % 255; if( res < ( ITERATIONS >> 1 ) ) res = RGB( n_res << 2, n_res << 3, n_res << 4 ); else res = RGB( n_res << 4, n_res << 2, n_res << 5 ); } bits[pos++] = res; } } bmp.saveBitmap( "./js.bmp" ); }
private:
int inSet( std::complex<long double> z, std::complex<long double> c ) { long double dist;//, three = 3.0; for( int ec = 0; ec < ITERATIONS; ec++ ) { z = z * z; z = z + c; dist = ( z.imag() * z.imag() ) + ( z.real() * z.real() ); if( dist > 3 ) return( ec ); } return 0; } myBitmap bmp;
}; int main( int argc, char* argv[] ) {
std::complex<long double> c; long double factor = FCT / BMP_SIZE; c.imag( ( factor * 184 ) + -1.4 ); c.real( ( factor * 307 ) + -2.0 ); julia j; j.draw( c ); return 0;
} </lang>
COBOL
Plots—in ASCII or EBCDIC art—a Julia set for the function f(z) = z2 + c, based on a value of c input by the user (real part then imaginary part, pressing the carriage return key after each). The sample output is for the inputs -0.8 and 0.156. <lang cobol>IDENTIFICATION DIVISION. PROGRAM-ID. JULIA-SET-PROGRAM. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-COMPLEX-CONSTANT.
05 C-REAL PIC S9V999. 05 C-IMAGINARY PIC S9V999.
01 WS-ARGAND-PLANE.
05 X PIC S9(9)V999. 05 Y PIC S9(9)V999.
01 WS-COMPLEX-VARIABLE.
05 Z-REAL PIC S9(9)V999. 05 Z-IMAGINARY PIC S9(9)V999.
01 WS-TEMPORARY-RESULTS.
05 X-SQUARED PIC S9(9)V999. 05 Y-SQUARED PIC S9(9)V999. 05 X-TIMES-Y PIC S9(9)V999. 05 Z-REAL-SQUARED PIC S9(9)V999.
01 WS-LOOP-COUNTERS.
05 HORIZONTAL PIC 999. 05 VERTICAL PIC 999. 05 ITERATIONS PIC 99.
77 WS-PLOT-CHARACTER PIC X. PROCEDURE DIVISION. INPUT-COMPLEX-CONSTANT-PARAGRAPH.
ACCEPT C-REAL FROM CONSOLE. ACCEPT C-IMAGINARY FROM CONSOLE.
CONTROL-PARAGRAPH.
PERFORM OUTER-LOOP-PARAGRAPH VARYING VERTICAL FROM 1 BY 10 UNTIL VERTICAL IS GREATER THAN 320. STOP RUN.
OUTER-LOOP-PARAGRAPH.
PERFORM COMPUTATION-PARAGRAPH VARYING HORIZONTAL FROM 1 BY 10 UNTIL HORIZONTAL IS GREATER THAN 560. DISPLAY UPON CONSOLE.
COMPUTATION-PARAGRAPH.
SUBTRACT 280 FROM HORIZONTAL GIVING X. SUBTRACT 160 FROM VERTICAL GIVING Y. DIVIDE X BY 200 GIVING X. DIVIDE Y BY 100 GIVING Y. MOVE '#' TO WS-PLOT-CHARACTER. PERFORM COMPLEX-MULTIPLICATION-PARAGRAPH VARYING ITERATIONS FROM 1 BY 1 UNTIL ITERATIONS IS GREATER THAN 50 OR WS-PLOT-CHARACTER IS EQUAL TO SPACE. DISPLAY WS-PLOT-CHARACTER UPON CONSOLE WITH NO ADVANCING.
COMPLEX-MULTIPLICATION-PARAGRAPH.
MULTIPLY X BY X GIVING X-SQUARED. MULTIPLY Y BY Y GIVING Y-SQUARED. SUBTRACT Y-SQUARED FROM X-SQUARED GIVING Z-REAL. ADD C-REAL TO Z-REAL. MULTIPLY X BY Y GIVING X-TIMES-Y. MULTIPLY X-TIMES-Y BY 2 GIVING Z-IMAGINARY. ADD C-IMAGINARY TO Z-IMAGINARY. MULTIPLY Z-REAL BY Z-REAL GIVING Z-REAL-SQUARED. IF Z-REAL-SQUARED IS GREATER THAN 10000 THEN MOVE SPACE TO WS-PLOT-CHARACTER. MOVE Z-REAL TO X. MOVE Z-IMAGINARY TO Y.</lang>
- Output:
### ## ## # ### #### # ################ ### # # # ############### # ####### ## ##### ######## # # ##### ## ######## ### ######## # ### ### # ## # ## # #### # # # #### # #### ### # # # ### # # ######### # ## ###### # ######### # ######### ###### # ### ### ## ## ############ # # # ######### ## ## # ##### #### # # ### #
Elixir
<lang elixir>defmodule Julia do
def set(c_real, c_imag) do IO.puts "#{c_real}, #{c_imag}" vlist = Enum.take_every(-100..100, 4) hlist = Enum.take_every(-280..280, 4) Enum.each(vlist, fn v -> Enum.map(hlist, fn h -> loop(c_real, c_imag, h/200, v/100, "#", 0) end) |> IO.puts end) end defp loop(_, _, _, _, char, i) when i>=50, do: char defp loop(_, _, _, _, " ", _), do: " " defp loop(c_real, c_imag, x, y, char, i) do z_real = (x * x - y * y) + c_real z_imag = x * y * 2 + c_imag char = if z_real * z_real > 10000, do: " ", else: char loop(c_real, c_imag, z_real, z_imag, char, i+1) end
end
c_real = if r=Enum.at(System.argv, 0), do: Float.parse(r) |> elem(0), else: -0.8 c_imag = if c=Enum.at(System.argv, 1), do: Float.parse(c) |> elem(0), else: 0.156 Julia.set(c_real, c_imag)</lang>
- Output:
-0.8, 0.156 # # ## ####### ## #### ## # #### ## # # # ### ### # ## # # ###### ########## # # # # ###### ########## # # ### ### # ############ ###### # ################ ################### # # ### # ################ #################### ## # ### ## ## ############################## ### #### # ####### ### # ## ## # ##################### # #### ## #### ### ########### ###### # # ##### ##################### # # ## ###################### ### ####### #### # ####################### # ### ############ ### ## ## ## ## ## ################# ######################## ### ########### ## ### ### ################# ## ###### # # ################### # ##### ## ######## # ### # ###### ############ ## ## # ### ############## # ## ### ## # #### # # ## ### ## ########### ## #### ############# ## # ## ### ## ## ####### ## ##### ######### ############# ### # # ####### # # ### ############# ######### ##### ## ####### ## ## ### ## # ## ############# #### ## ########### ## ### ## # # #### # ## ### ## # ############## ### # ## ## ############ ###### # ### # ######## ## ##### # ################### # # ###### ## ################# ### ### ## ########### ### ######################## ################# ## ## ## ## ## ### ############ ### # ####################### # #### ####### ### ###################### ## # # ##################### ##### # # ###### ########### ### #### ## #### # ##################### # ## ## # ### ####### # #### ### ############################## ## ## ### # ## #################### ################ # ### # # ################### ################ # ###### ############ # ### ### # # ########## ###### # # # # ########## ###### # # ## # ### ### # # # ## #### # ## #### ## ####### ## # #
J
<lang j>load '~addons/graphics/fvj4/complex_dynamics.ijs' pal2=: 255,~0,<.(254$1 0.8 0.6)*Hue 5r6*(i.%<:)254 g=: [: %: 0.3746j0.102863 0.132565j0.389103 _0.373935j_0.353777 1&p. view_image pal2;b=:g escapetc (10 255) 500 zl_clur _1.5 1.5j1.5</lang>
See also: Fractals Visualization and J, 4th edition, Part 1 (by Clifford A. Reiter), Chapter 6
See http://webbox.lafayette.edu/~reiterc/mvp/ec_julia/index.html for some other examples. (That said, note that this is a link into a small college site and it might drift over time. In the past, for example, you would have had to use 'www' where it currently says 'webbox')
Java
<lang java>import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*;
public class JuliaSet extends JPanel {
private final int maxIter = 300; private final double zoom = 1; private double cY, cX;
public JuliaSet() { setPreferredSize(new Dimension(800, 600)); setBackground(Color.white); }
void drawJuliaSet(Graphics2D g) { int w = getWidth(); int h = getHeight(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
cX = -0.7; cY = 0.27015; double moveX = 0, moveY = 0; double zx, zy;
for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { zx = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX; zy = (y - h / 2) / (0.5 * zoom * h) + moveY; float i = maxIter; while (zx * zx + zy * zy < 4 && i > 0) { double tmp = zx * zx - zy * zy + cX; zy = 2.0 * zx * zy + cY; zx = tmp; i--; } int c = Color.HSBtoRGB((maxIter / i) % 1, 1, i > 0 ? 1 : 0); image.setRGB(x, y, c); } } g.drawImage(image, 0, 0, null); }
@Override public void paintComponent(Graphics gg) { super.paintComponent(gg); Graphics2D g = (Graphics2D) gg; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); drawJuliaSet(g); }
public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setTitle("Julia Set"); f.setResizable(false); f.add(new JuliaSet(), BorderLayout.CENTER); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); }); }
}</lang>
Julia
The following code creates the fractal as a ppm file named julia.ppm. There is no need of an external library to create this image since the ppm format is straightforward to generate.
<lang julia> function iter(z,c)
n = 0 while (abs2(z)<4) z = z^2+c ; n+=1 end return n
end
coord(i,j,w,h,a,b) = 2*a*(i-1)/(w-1) - a + im * (2*b*(j-1)/(h-1) - b)
palette(n) = string(min(3n,255)," ", min(n,255)," ", 0);
julia(c) = (w,h,a,b,i,j) -> palette(iter(coord(i,j,w,h,a,b), c))
writeppm(f; width=600,height=300,a=2,b=1,file="julia.ppm") =
open(file, "w") do out write(out, string("P3\n", width, " ", height, "\n255\n")) writedlm(out, [f(width,height,a,b,i,j) for j = 1:height, i = 1:width], '\n') end
</lang>
We can then produce a 600x300 ppm image of the Julia set associated to the parameter -0.786+0.147i as follows.
writeppm(julia(-0.786+0.147im))
The following code makes use of the library Images to build a png image.
<lang julia>using Images
w, h = 800, 600 img = Array(UInt8, h, w, 3)
maxIter = 50 c = -0.8+0.156im
function hsv2rgb(h, s, v)
c = v * s x = c * (1 - abs(((h/60) % 2) - 1)) m = v - c
r,g,b = if h < 60 (c, x, 0) elseif h < 120 (x, c, 0) elseif h < 180 (0, c, x) elseif h < 240 (0, x, c) elseif h < 300 (x, 0, c) else (c, 0, x) end
r = round(UInt8, (r + m) * 255) g = round(UInt8, (g + m) * 255) b = round(UInt8, (b + m) * 255)
b,g,r
end
for x in 1:w
for y in 1:h i = maxIter z = Complex((x - w/2) / w * 3, (y - h/2) / h * 2) while abs(z) < 2 && (i -= 1) > 0 z = z*z + c end r,g,b = hsv2rgb(i / maxIter * 360, 1, i > 1 ? 1 : 0) img[y,x,1] = r img[y,x,2] = g img[y,x,3] = b end
end
save("JuliaSet.png", colorim(img, "RGB"))</lang>
Perl
<lang perl>use Imager;
my($w, $h, $zoom) = (800, 600, 1); my $img = Imager->new(xsize => $w, ysize => $h, channels => 3);
my $maxIter = 255; my ($cX, $cY) = (-0.7, 0.27015); my ($moveX, $moveY) = (0, 0);
my $color = Imager::Color->new('#000000');
foreach my $x (0 .. $w - 1) {
foreach my $y (0 .. $h - 1) { my $zx = (1.5 * ($x - $w / 2) / (0.5 * $zoom * $w) + $moveX); my $zy = (($y - $h / 2) / (0.5 * $zoom * $h) + $moveY); my $i = $maxIter; while ($zx**2 + $zy**2 < 4 and --$i >= 0) { ($zy, $zx) = (2 * $zx * $zy + $cY, $zx**2 - $zy**2 + $cX); } $color->set(hsv => [$i / $maxIter * 360, 1, $i > 0 ? 1 : 0]); $img->setpixel(x => $x, y => $y, color => $color); }
}
$img->write(file => 'julia_set.png');</lang>
Perl 6
with the pallette swapped, just because.
<lang perl6>use Image::PNG::Portable;
my ($w, $h) = 800, 600; my $out = Image::PNG::Portable.new: :width($w), :height($h);
my $maxIter = 255; my $c = -0.7 + 0.27015i;
julia($out);
$out.write: 'Julia-set-perl6.png';
sub julia ( $png ) {
for ^$w -> $x { for ^$h -> $y { my $z = Complex.new(($x - $w / 2) / $w * 3, ($y - $h / 2) / $h * 2); my $i = $maxIter; while (abs($z) < 2 and --$i) { $z = $z*$z + $c; } $png.set: $x, $y, |hsv2rgb($i / $maxIter * 360, 1, ?$i).reverse; } }
}
sub hsv2rgb ( $h, $s, $v ){
my $c = $v * $s; my $x = $c * (1 - abs( (($h/60) % 2) - 1 ) ); my $m = $v - $c; my ($r, $g, $b) = do given $h { when 0..^60 { $c, $x, 0 } when 60..^120 { $x, $c, 0 } when 120..^180 { 0, $c, $x } when 180..^240 { 0, $x, $c } when 240..^300 { $x, 0, $c } when 300..^360 { $c, 0, $x } } ( $r, $g, $b ) = map { (($_+$m) * 255).Int }, $r, $g, $b;
}</lang>
Processing
<lang java>void setup() {
size(640, 480);
}
float cX = -0.7; float cY = 0.27015; float zx, zy; float maxIter = 300;
void draw() {
for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { zx = 1.5 * (x - width / 2) / (0.5 * width); zy = (y - height / 2) / (0.5 * height); float i = maxIter; while (zx * zx + zy * zy < 4 && i > 0) { float tmp = zx * zx - zy * zy + cX; zy = 2.0 * zx * zy + cY; zx = tmp; i -= 1; } color c = hsv2rgb(i / maxIter * 360, 1, i > 1 ? 1 : 0); set(x, y, c); } } noLoop();
}
color hsv2rgb(float h, float s, float v) {
float c = v * s; float x = c * (1 - abs(((h/60) % 2) - 1)); float m = v - c;
float r, g, b; if (h < 60) { r = c; g = x; b = 0; } else if (h < 120) { r = x; g = c; b = 0; } else if (h < 180) { r = 0; g = c; b = x; } else if (h < 240) { r = 0; g = x; b = c; } else if (h < 300) { r = x; g = 0; b = c; } else { r = c; g = 0; b = x; }
int ri = round((r + m) * 255); int gi = round((g + m) * 255); int bi = round((b + m) * 255);
return color(ri, gi, bi);
}</lang>
Python
<lang python>from PIL import Image
if __name__ == "__main__": w, h, zoom = 800,600,1 bitmap = Image.new("RGB", (w, h), "white") pix = bitmap.load()
cX, cY = -0.7, 0.27015 moveX, moveY = 0.0, 0.0 maxIter = 255
for x in range(w): for y in range(h): zx = 1.5*(x - w/2)/(0.5*zoom*w) + moveX zy = 1.0*(y - h/2)/(0.5*zoom*h) + moveY i = maxIter while zx*zx + zy*zy < 4 and i > 1: tmp = zx*zx - zy*zy + cX zy,zx = 2.0*zx*zy + cY, tmp i -= 1 # convert byte to RGB (3 bytes), kinda magic to get nice colors pix[x,y] = (i << 21) + (i << 10) + i*8
bitmap.show()</lang>
Racket
<lang racket>
- Based on Mandelbrot code (GPL) from
- https://github.com/hebr3/Mandelbrot-Set-Racket/blob/master/Mandelbrot.v6.rkt
- Julia set algoithm (and coloring) from
- http://lodev.org/cgtutor/juliamandelbrot.html
- HSV code (GPL) based on
- https://github.com/takikawa/pict-utils/blob/master/pict-utils/hsv.rkt
- lang racket
- Required to generate image
(require picturing-programs)
- CONSTANTS - NUMBERS
(define DEPTH 300) (define WIDTH 800) (define HEIGHT 600)
- Structures
(struct posn [x y] #:transparent)
- CONSTANTS - GRAPHIC
(define BACKGROUND (rectangle WIDTH HEIGHT 'solid 'grey)) (define jcnst (posn -0.7 0.27015))
- PROCEDURES
- make an RGB color from HSV values
(define (make-color/hsv hue saturation value)
(define chroma (* saturation value)) (define hue* (/ (remainder* hue (* 2 pi)) (/ pi 3))) (define X (* chroma (- 1 (abs (- (remainder* hue* 2) 1))))) (define-values (r1 g1 b1) (cond [(and (<= 0 hue*) (< hue* 1)) (values chroma X 0)] [(and (<= 1 hue*) (< hue* 2)) (values X chroma 0)] [(and (<= 2 hue*) (< hue* 3)) (values 0 chroma X)] [(and (<= 3 hue*) (< hue* 4)) (values 0 X chroma)] [(and (<= 4 hue*) (< hue* 5)) (values X 0 chroma)] [(and (<= 5 hue*) (< hue* 6)) (values chroma 0 X)])) (define m (- value chroma)) (apply make-color (map (λ (x) (exact-round (* 255 (+ x m)))) (list r1 g1 b1))))
- general remainder
(define (remainder* n1 n2)
(define num-divides (/ n1 n2)) (- n1 (* (floor num-divides) n2)))
- Posn -> Number
- Returns the magnitude of the posn
(define (posn-mag pt)
(let ([pt-x (posn-x pt)] [pt-y (posn-y pt)]) (sqrt (+ (* pt-x pt-x) (* pt-y pt-y)))))
- Posn Posn -> Posn
- Posn addition
(define (posn+ pt1 pt2)
(let ([pt1-x (posn-x pt1)] [pt1-y (posn-y pt1)] [pt2-x (posn-x pt2)] [pt2-y (posn-y pt2)]) (posn (+ pt1-x pt2-x) (+ pt1-y pt2-y))))
- Posn Posn -> Posn
- Posn multiplication
(define (posn* pt1 pt2)
(let ([x1 (posn-x pt1)] [y1 (posn-y pt1)] [x2 (posn-x pt2)] [y2 (posn-y pt2)]) (posn (- (* x1 x2) (* y1 y2)) (+ (* x1 y2) (* x2 y1)))))
- Posn -> Posn
- Posn square
(define (posn-sqr pt)
(posn* pt pt))
- Posn -> Number
- Returns the julia set escape number for a given complex number
- given in rectangular coordinates.
(define (julia-set-number start)
(define (iter result count) (cond [(> (posn-mag result) 2) (sub1 count)] [(> count DEPTH) DEPTH] [else (iter (posn+ jcnst (posn-sqr result)) (add1 count))])) (iter start 1))
- Number -> Number
- Returns the scaled location of a point
(define (scaled-x x)
(/ (* 1.5 (- x (/ WIDTH 2))) (* 0.5 WIDTH)))
(define (scaled-y y)
(/ (- y (/ HEIGHT 2)) (* 0.5 HEIGHT)))
- Generates image
(define M-Image
(map-image (λ (x y c) (let* ([ref (julia-set-number (posn (scaled-x x) (scaled-y y)))]) (cond [(= ref DEPTH) (name->color 'black)] [else (make-color/hsv (* 2 (* pi (/ ref DEPTH))) 1 1)]) )) BACKGROUND))
M-Image ;show image if using drracket
(save-image M-Image "julias.png") </lang>
REXX
- which is a
<lang rexx>/*REXX program displays an ASCII plot (character plot) of a Julia set. */ parse arg real imag fine . /*obtain optional arguments from the CL*/ if real== | real=="," then real= -0.8 /*Not specified? Then use the default.*/ if imag== | imag=="," then imag= 0.156 /* " " " " " " */ if fine== | fine=="," then fine= 50 /* " " " " " " */ _=scrsize(); parse var _ sd sw; sd=sd-4; sw=sw-1 /*obtain useable area for the terminal.*/
/*$: the plot line that is constructed*/ do v= -sd%2 to sd%2; $= /*step through vertical axis values.*/ do h= -sw%2 to sw%2 /* " " horizontal " " */ x=h/sw*2 /*calculate the initial X value. */ y=v/sd*2 /* " " " Y " */ @='■'; do fine /*FINE: is the "fineness" for the plot.*/ zr=x*x - y*y + real /*calculate a new real Julia point.*/ zi=x*y*2 + imag /* " " " imaginal " " */ if zr**2>10000 then do; @=' '; leave; end /*is ZR too large? */ x=zr; y=zi /*use this new point.*/ end /*50*/ $=$ || @ /*append the plot char to the plot line*/ end /*h*/ if $\= then say strip($, 'T') /*only display a plot line if non-blank*/ end /*v*/ /*stick a fork in it, we're all done. */</lang>
This REXX program makes use of scrsize REXX program (or BIF) which is used to determine the screen size of the terminal (console),
and the plot size is adjusted according.
The SCRSIZE.REX REXX program is included here ──► SCRSIZE.REX.
(final) output when using the default input (screen size was 200x420):
(Shown at 1/6 size.)
output when the defaults are used:
■■ ■ ■ ■■ ■■ ■■■■■■■ ■ ■■■■ ■■■ ■■■■ ■■■■■ ■■ ■■■■ ■■ ■■■ ■■■■■ ■■■ ■■■■ ■■■■■■ ■■ ■ ■■■ ■■■■ ■■ ■■■■■■■ ■ ■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■ ■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■ ■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■ ■■■■ ■ ■■■■■■■■■■■■ ■ ■■■■ ■ ■ ■■■■■■■■■■ ■ ■ ■■■■■■■■■ ■ ■ ■ ■■■■■■■■■■■■ ■■ ■■■■■■ ■■■ ■■ ■■■■■■■■ ■■■ ■■■■■■■ ■■ ■ ■ ■■ ■ ■■■■■■■■■ ■ ■■■ ■■ ■■■■■ ■■■■ ■■ ■■■■■■■ ■■ ■■■■■■■■■ ■■■■■ ■ ■■■■■■■■■■■■■■ ■■■ ■■■■■ ■■■■■■ ■ ■■ ■■ ■■■■■■■■■■ ■ ■■■ ■■■■■ ■■ ■ ■■ ■■■ ■■■■■■■■■■■ ■■■ ■■■■■ ■■■■■■■■ ■ ■■■■ ■ ■ ■ ■■ ■ ■ ■ ■■■ ■■■ ■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■ ■ ■■■ ■■■■ ■■ ■■■■■■ ■ ■ ■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■ ■■■ ■ ■■■■ ■■■■■■ ■ ■ ■ ■ ■■■■■■ ■■ ■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■ ■ ■■■■■ ■■■■■ ■■■■■■ ■■ ■■■ ■■■■■■ ■■■ ■■■■■■■■■ ■■■■ ■ ■■■■■■■■■■■■■■■■■■■ ■■■■ ■ ■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■ ■ ■■ ■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■ ■■ ■■■■ ■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■ ■■■ ■■ ■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■ ■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■■■■■■■ ■ ■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■ ■■■■■■■■■■■■■■■ ■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■ ■■■■■■■■ ■■■ ■■■■■■■■■■■ ■ ■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■■ ■■ ■ ■ ■ ■ ■■■ ■ ■■ ■■■■■■■■■■■ ■■■■■■■■ ■ ■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■ ■ ■ ■■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■■ ■ ■■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■■ ■■■■■■■ ■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■ ■ ■■ ■■■ ■■ ■■■■■■■■■■■■■■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■ ■ ■■■■■■■ ■■■■■■■■ ■■■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■ ■■■■■■■■■■■■■■■ ■■■■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■ ■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■ ■■■■■■■■■■■■■ ■■ ■■■ ■■ ■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■ ■■■ ■ ■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■ ■■■■■ ■■■■■■ ■ ■ ■■ ■■■ ■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■ ■ ■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■■ ■■ ■■■■■ ■■ ■ ■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■■ ■■■■ ■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■ ■ ■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■ ■■ ■ ■■ ■■■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■ ■■ ■ ■■ ■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■ ■■■■ ■■■ ■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■ ■■■ ■■■■■■■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■ ■ ■■ ■ ■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■■■■ ■■■ ■ ■■ ■■■■■ ■■■■■■■■ ■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■ ■ ■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■ ■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■■■■ ■ ■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■ ■■■ ■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■ ■■■■■■■■■■■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■■■■■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■ ■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■ ■■■■■■■■■■ ■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■ ■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■ ■■■■■ ■■■■■■■ ■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■ ■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■ ■ ■■■■■■■■■■■ ■■■■■■■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■ ■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■ ■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■ ■■■■■■■■ ■ ■■■■■■■■■■■ ■■■■■■■■ ■ ■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■ ■■■■■■ ■■■ ■■■■ ■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■ ■■■■■ ■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■ ■ ■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■ ■ ■■■■■■■■■■■■■ ■■■■■■■ ■ ■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■ ■■ ■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■ ■■■■■ ■■■ ■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■■ ■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■ ■ ■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■ ■■ ■■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■■■■ ■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■ ■ ■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■ ■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■ ■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■ ■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■ ■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■ ■ ■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■ ■■■■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■■ ■■ ■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■ ■ ■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■ ■■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■ ■■■ ■■■■■ ■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■ ■■ ■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■ ■ ■■■■■■■ ■■■■■■■■■■■■■ ■ ■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■ ■ ■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■ ■■■■■ ■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■ ■■■■ ■■■ ■■■■■■ ■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■ ■ ■■■■■■■■ ■■■■■■■■■■■ ■ ■■■■■■■■ ■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■ ■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■ ■ ■■■ ■■■■■■■■ ■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■■■■■■■ ■■■■■■■■■■■ ■ ■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■ ■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■ ■■■■■■■ ■■■■■ ■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■ ■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■■ ■■■■■■■■■■ ■ ■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■ ■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■■■■■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■■■■■■■■■■■ ■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■ ■■■ ■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■ ■ ■■■■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■ ■ ■■■ ■■ ■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■ ■ ■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■ ■■■■■■■■ ■■■■■ ■■ ■ ■■■ ■■■■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■ ■ ■■ ■ ■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■■■■■■■ ■■■ ■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■ ■■■ ■■■■ ■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■ ■■ ■ ■■ ■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■ ■■■■■ ■■ ■ ■■ ■■■ ■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■■ ■■■■ ■ ■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■■■■■■■ ■■■■ ■■■■■■■■ ■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■ ■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■ ■ ■■ ■■■■■ ■■ ■■■■■■■■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■ ■ ■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■ ■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■ ■ ■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■ ■■■ ■■ ■ ■ ■■■■■■ ■■■■■ ■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■ ■ ■ ■■■ ■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■ ■■ ■■■ ■■ ■■■■■■■■■■■■■ ■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■ ■■■ ■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■■■■ ■■■■■■■■■■■■■■■ ■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■ ■ ■■■ ■■■■■■■■ ■■■■■■■ ■ ■ ■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■ ■■■■■■■■■■■■■■ ■■ ■■■ ■■ ■ ■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■ ■■■■■■■ ■■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■■ ■ ■■■ ■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■ ■■■■■■■■■■■■■■■■■■ ■■■ ■ ■ ■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■ ■ ■■■■■■■■ ■■■■■■■■■■■ ■■ ■ ■■■ ■ ■ ■ ■ ■■ ■■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■■■ ■ ■ ■■■■■■■■■■■ ■■■ ■■■■■■■■ ■ ■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■ ■■■■ ■■■■■■■■■■■■■■■ ■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■■ ■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■ ■■ ■ ■■ ■ ■■■■■■■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■ ■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■ ■■ ■■ ■■■ ■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■ ■■■■ ■■ ■■■■ ■■■■■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■■■■■■■ ■■ ■ ■■ ■■■■■■■■■■■■■■■■■■ ■■■■■■■■■■■■■■■■ ■ ■■■■ ■■■■■■■■■■■■■■■■■■■ ■ ■■■■ ■■■■■■■■■ ■■■ ■■■■■■ ■■■ ■■ ■■■■■■ ■■■■■ ■■■■■ ■ ■■ ■ ■ ■■ ■■■■■■■■■■■■■■■■■ ■■■■■■■■■■ ■ ■■ ■■■■■■ ■ ■ ■ ■ ■■■■■■ ■■■■ ■ ■■■ ■■■ ■ ■ ■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■ ■ ■ ■■■■■■ ■■ ■■■■ ■■■ ■ ■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■■ ■■■ ■■■ ■ ■ ■ ■■ ■ ■ ■ ■■■■ ■ ■■■■■■■■ ■■■■■ ■■■ ■■■■■■■■■■■ ■■■ ■■ ■ ■■ ■■■■■ ■■■ ■ ■■■■■■■■■■ ■■ ■■ ■ ■■■■■■ ■■■■■ ■■■ ■■■■■■■■■■■■■■ ■ ■■■■■ ■■■■■■■■■ ■■ ■■■■■■■ ■■ ■■■■ ■■■■■ ■■ ■■■ ■ ■■■■■■■■■ ■ ■■ ■ ■ ■■ ■■■■■■■ ■■■ ■■■■■■■■ ■■ ■■■ ■■■■■■ ■■ ■■■■■■■■■■■■ ■ ■ ■ ■■■■■■■■■ ■ ■ ■■■■■■■■■■ ■ ■ ■■■■ ■ ■■■■■■■■■■■■ ■ ■■■■ ■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■ ■■■■■■■■■■ ■■■■■ ■■■■■■■■■■■■■■■ ■ ■■■■■■■■■■■■■ ■■■■■■■■■■■■■■ ■ ■ ■■■■■ ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ ■■■ ■ ■■■■■■■■■■■■■■ ■■■■■■■■■■■ ■■■ ■■ ■■■■■■■■■■■■■■■■■■■ ■■■■■■■■ ■ ■ ■■■■■■■ ■■ ■■■■ ■■■ ■ ■■ ■■■■■■ ■■■■ ■■■ ■■■■■ ■■■ ■■ ■■■■ ■■ ■■■■■ ■■■■ ■■■ ■■■■ ■ ■■■■■■■ ■■ ■■ ■ ■ ■■ ∙∙
Ruby
<lang ruby>def julia(c_real, c_imag)
puts Complex(c_real, c_imag) -1.0.step(1.0, 0.04) do |v| puts -1.4.step(1.4, 0.02).map{|h| judge(c_real, c_imag, h, v)}.join end
end
def judge(c_real, c_imag, x, y)
50.times do z_real = (x * x - y * y) + c_real z_imag = x * y * 2 + c_imag return " " if z_real**2 > 10000 x, y = z_real, z_imag end "#"
end
julia(-0.8, 0.156)</lang>
- Output:
-0.8+0.156i # # ## ####### ## #### ## # #### ## # # # ### ### # ## # # ###### ########## # # # # ###### ########## # # ### ### # ############ ###### # ################ ################### # # ### # ################ #################### ## # ### ## ## ############################## ### #### # ####### ### # ## ## # ##################### # #### ## #### ### ########### ###### # # ##### ##################### # # ## ###################### ### ####### #### # ####################### # ### ############ ### ## ## ## ## ## ################# ######################## ### ########### ## ### ### ################# ## ###### # # ################### # ##### ## ######## # ### # ###### ############ ## ## # ### ############## # ## ### ## # #### # # ## ### ## ########### ## #### ############# ## # ## ### ## ## ####### ## ##### ######### ############# ### # # ####### # # ### ############# ######### ##### ## ####### ## ## ### ## # ## ############# #### ## ########### ## ### ## # # #### # ## ### ## # ############## ### # ## ## ############ ###### # ### # ######## ## ##### # ################### # # ###### ## ################# ### ### ## ########### ### ######################## ################# ## ## ## ## ## ### ############ ### # ####################### # #### ####### ### ###################### ## # # ##################### ##### # # ###### ########### ### #### ## #### # ##################### # ## ## # ### ####### # #### ### ############################## ## ## ### # ## #################### ################ # ### # # ################### ################ # ###### ############ # ### ### # # ########## ###### # # # # ########## ###### # # ## # ### ### # # # ## #### # ## #### ## ####### ## # #
Sidef
<lang ruby>require('Imager')
var (w, h) = (640, 480) var img = %s'Imager'.new(xsize => w, ysize => h, channels => 3)
var maxIter = 50 var c = Complex(-0.388, 0.613)
var color = %s'Imager::Color'.new('#000000')
for x,y in (^w ~X ^h) {
var i = maxIter var z = Complex((x - w/2) / w * 3, (y - h/2) / h * 2) while (z.abs < 2 && --i) { z = (z*z + c) } color.set(hsv => [i / maxIter * 360, 1, i]) img.setpixel(x => x, y => y, color => color)
}
img.write(file => "JuliaSet_sidef.png")</lang>
This version generates an ASCII representation: <lang ruby>var (w, h) = (141, 50)
var maxIter = 40 var c = Complex(-0.8, 0.156)
for y in ^h {
for x in ^w { var i = maxIter var z = Complex(3 * (x - w/2) / w, 2 * (y - h/2) / h) while (z.abs < 2 && --i) { z = (z*z + c) } print (i > 0 ? ' ' : '#') } print "\n"
}</lang>
- Output:
## ## ####### ######## # ## # ### ## # # ##### #### ## ## # ###### ########## # ######## ########## # ## ###### ######################## ### ################ ################### ## ## # ### # # ##################################### # ### ## # # ############################# ########### # ###### ### # # ## ########################### # ######## ################# # # # #### ##################### ### #### ##################### ### ############ ###################### # # ### ################ ### # # # ### # ################# ###################### ## ########### # ## ###### ########################### #################### ###### ## ########## ### # ### # ## ################ ## ###### ################# ######## ## # ###### ## ## #### ## # # ########### # #### ############# #### ### ####### ########### ## ###### ########## ############ ## # ########## # ## ############ ########## ###### ## ########### ####### ### #### ############# #### # ########### # # ### #### ## ## ###### # ## ######## ################# ###### ## ################ ## # ### # ### ########## ## ###### #################### ########################### ###### ## # ########### ## ###################### ################# # ### # # # ### ################ ### # # ###################### ############ ### ##################### #### ### ##################### #### # # # ################# ######## # ########################### ## # # ### ###### # ########### ############################# # # ## ### # ##################################### # # ### # ## ## ################### ################ ### ######################## ###### ## # ########## ######## # ########## ###### # ## ## #### ##### # # ## ### # ## # ######## ####### ## ##
zkl
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
<lang zkl>fcn juliaSet{
w,h,zoom:=800,600, 1; bitmap:=PPM(w,h,0xFF|FF|FF); // White background
cX,cY:=-0.7, 0.27015; moveX,moveY:=0.0, 0.0; maxIter:=255;
foreach x,y in (w,h){ zx:=1.5*(x - w/2)/(0.5*zoom*w) + moveX; zy:=1.0*(y - h/2)/(0.5*zoom*h) + moveY; i:=maxIter; while(zx*zx + zy*zy < 4 and i > 1){
tmp:=zx*zx - zy*zy + cX; zy,zx=2.0*zx*zy + cY, tmp; i-=1;
} // convert byte to RGB (3 bytes), kinda magic to get nice colors bitmap[x,y]=i.shiftLeft(21) + i.shiftLeft(10) + i*8; }
bitmap.writeJPGFile("juliaSet.jpg",True);
}();</lang>