Barnsley fern: Difference between revisions
m (→{{header|Processing}}: minor code simplifications) |
m (no longer draft) |
||
Line 1: | Line 1: | ||
{{ |
{{task}} |
||
A [[wp:Barnsley_fern|Barnsley fern]] is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS). |
A [[wp:Barnsley_fern|Barnsley fern]] is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS). |
Revision as of 20:31, 29 May 2016
You are encouraged to solve this task according to the task description, using any language you may know.
A Barnsley fern is a fractal named after British mathematician Michael Barnsley and can be created using an iterated function system (IFS).
The task: create this fractal fern, using the following transformations:
- ƒ1 (chosen 1% of the time)
xn + 1 = 0 yn + 1 = 0.16 yn
- ƒ2 (chosen 85% of the time)
xn + 1 = 0.85 xn + 0.04 yn yn + 1 = −0.04 xn + 0.85 yn + 1.6
- ƒ3 (chosen 7% of the time)
xn + 1 = 0.2 xn − 0.26 yn yn + 1 = 0.23 xn + 0.22 yn + 1.6
- ƒ4 (chosen 7% of the time)
xn + 1 = −0.15 xn + 0.28 yn yn + 1 = 0.26 xn + 0.24 yn + 0.44.
Starting position: x = 0, y = 0
C++
<lang cpp>
- include <windows.h>
- include <ctime>
- include <string>
const int BMP_SIZE = 600, ITERATIONS = static_cast<int>( 15e5 );
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; }
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 fern { public:
void draw() { bmp.create( BMP_SIZE, BMP_SIZE ); float x = 0, y = 0; HDC dc = bmp.getDC(); int hs = BMP_SIZE >> 1; for( int f = 0; f < ITERATIONS; f++ ) { SetPixel( dc, hs + static_cast<int>( x * 55.f ), BMP_SIZE - 15 - static_cast<int>( y * 55.f ), RGB( static_cast<int>( rnd() * 80.f ) + 20, static_cast<int>( rnd() * 128.f ) + 128, static_cast<int>( rnd() * 80.f ) + 30 ) ); getXY( x, y ); } bmp.saveBitmap( "./bf.bmp" ); }
private:
void getXY( float& x, float& y ) { float g, xl, yl; g = rnd(); if( g < .01f ) { xl = 0; yl = .16f * y; } else if( g < .07f ) { xl = .2f * x - .26f * y; yl = .23f * x + .22f * y + 1.6f; } else if( g < .14f ) { xl = -.15f * x + .28f * y; yl = .26f * x + .24f * y + .44f; } else { xl = .85f * x + .04f * y; yl = -.04f * x + .85f * y + 1.6f; } x = xl; y = yl; } float rnd() { return static_cast<float>( rand() ) / static_cast<float>( RAND_MAX ); } myBitmap bmp;
}; int main( int argc, char* argv[]) {
srand( static_cast<unsigned>( time( 0 ) ) ); fern f; f.draw(); return 0;
} </lang>
J
<lang j>require 'plot'
f=: |: 0 ". ];._2 noun define
0 0 0 0.16 0 0 0.01 0.85 -0.04 0.04 0.85 0 1.60 0.85 0.20 0.23 -0.26 0.22 0 1.60 0.07 -0.15 0.26 0.28 0.24 0 0.44 0.07
)
fm=: {&(|: 2 2 $ f) fa=: {&(|: 4 5 { f) prob=: (+/\ 6 { f) I. ?@0:
ifs=: (fa@] + fm@] +/ .* [) prob getPoints=: ifs^:(<200000) plotFern=: 'dot;grids 0 0;tics 0 0;labels 0 0;color green' plot ;/@|:
plotFern getPoints 0 0</lang>
Java
<lang java>import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*;
public class BarnsleyFern extends JPanel {
BufferedImage img;
public BarnsleyFern() { final int dim = 640; setPreferredSize(new Dimension(dim, dim)); setBackground(Color.white); img = new BufferedImage(dim, dim, BufferedImage.TYPE_INT_ARGB); createFern(dim, dim); }
void createFern(int w, int h) { double x = 0; double y = 0;
for (int i = 0; i < 200_000; i++) { double tmpx, tmpy; double r = Math.random();
if (r <= 0.01) { tmpx = 0; tmpy = 0.16 * y; } else if (r <= 0.08) { tmpx = 0.2 * x - 0.26 * y; tmpy = 0.23 * x + 0.22 * y + 1.6; } else if (r <= 0.15) { tmpx = -0.15 * x + 0.28 * y; tmpy = 0.26 * x + 0.24 * y + 0.44; } else { tmpx = 0.85 * x + 0.04 * y; tmpy = -0.04 * x + 0.85 * y + 1.6; } x = tmpx; y = tmpy;
img.setRGB((int) Math.round(w / 2 + x * w / 11), (int) Math.round(h - y * h / 11), 0xFF32CD32); } }
@Override public void paintComponent(Graphics gg) { super.paintComponent(gg); Graphics2D g = (Graphics2D) gg; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(img, 0, 0, null); }
public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setTitle("Barnsley Fern"); f.setResizable(false); f.add(new BarnsleyFern(), BorderLayout.CENTER); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); }); }
}</lang>
Perl
<lang perl>use Imager;
my $w = 640; my $h = 640;
my $img = Imager->new(xsize => $w, ysize => $h, channels => 3); my $green = Imager::Color->new('#00FF00');
my ($x, $y) = (0, 0);
foreach (1 .. 2e5) {
my $r = rand(100); ($x, $y) = do { if ($r <= 1) { ( 0.00 * $x - 0.00 * $y, 0.00 * $x + 0.16 * $y + 0.00) } elsif ($r <= 8) { ( 0.20 * $x - 0.26 * $y, 0.23 * $x + 0.22 * $y + 1.60) } elsif ($r <= 15) { (-0.15 * $x + 0.28 * $y, 0.26 * $x + 0.24 * $y + 0.44) } else { ( 0.85 * $x + 0.04 * $y, -0.04 * $x + 0.85 * $y + 1.60) } }; $img->setpixel(x => $w / 2 + $x * 60, y => $y * 60, color => $green);
}
$img->flip(dir => 'v'); $img->write(file => 'barnsleyFern.png');</lang>
Perl 6
<lang perl6>use Image::PNG::Portable;
my ($w, $h) = (640, 640);
my $png = Image::PNG::Portable.new: :width($w), :height($h);
my ($x, $y) = (0, 0);
for ^2e5 {
my $r = 100.rand; ($x, $y) = do given $r { when $r <= 1 { ( 0, 0.16 * $y ) } when $r <= 8 { ( 0.20 * $x - 0.26 * $y, 0.23 * $x + 0.22 * $y + 1.60) } when $r <= 15 { (-0.15 * $x + 0.28 * $y, 0.26 * $x + 0.24 * $y + 0.44) } default { ( 0.85 * $x + 0.04 * $y, -0.04 * $x + 0.85 * $y + 1.60) } }; $png.set(($w / 2 + $x * 60).Int, $h - ($y * 60).Int, 0, 255, 0);
}
$png.write: 'Barnsley-fern-perl6.png';</lang>
Processing
<lang java>void setup() {
size(640, 640); background(0, 0, 0);
}
float x = 0; float y = 0;
void draw() {
for (int i = 0; i < 100000; i++) {
float xt = 0; float yt = 0;
float r = random(100);
if (r <= 1) { xt = 0; yt = 0.16*y; } else if (r <= 8) { xt = 0.20*x - 0.26*y; yt = 0.23*x + 0.22*y + 1.60; } else if (r <= 15) { xt = -0.15*x + 0.28*y; yt = 0.26*x + 0.24*y + 0.44; } else { xt = 0.85*x + 0.04*y; yt = -0.04*x + 0.85*y + 1.60; }
x = xt; y = yt;
int m = round(width/2 + 60*x); int n = height-round(60*y);
set(m, n, #00ff00); } noLoop();
}</lang>
Sidef
<lang ruby>require('Imager')
var w = 640 var h = 640
var img = %s<Imager>.new(xsize => w, ysize => h, channels => 3) var green = %s<Imager::Color>.new('#00FF00')
var (x, y) = (0, 0)
for r in (^1e5 -> lazy.map { 100.rand }) {
(x, y) = ( if (r <= 1) { ( 0.00*x - 0.00*y, 0.00*x + 0.16*y + 0.00) } elsif (r <= 8) { ( 0.20*x - 0.26*y, 0.23*x + 0.22*y + 1.60) } elsif (r <= 15) { (-0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44) } else { ( 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.60) } ) img.setpixel(x => w/2 + 60*x, y => 60*y, color => green)
}
img.flip(dir => 'v') img.write(file => 'barnsleyFern.png')</lang>
tcl
See Tcl-Wiki [_ttp://wiki.tcl.tk/10492 Fern Fractal]
zkl
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
<lang zkl>fcn barnsleyFern(){
w,h:=640,640; bitmap:=PPM(w+1,h+1,0xFF|FF|FF); // White background
x,y, nx,ny:=0.0, 0.0, 0.0, 0.0; do(0d100_000){ r:=(0).random(100); // [0..100)% if (r<= 1) nx,ny= 0, 0.16*y; else if(r<= 8) nx,ny= 0.2*x - 0.26*y, 0.23*x + 0.22*y + 1.6; else if(r<=15) nx,ny=-0.15*x + 0.28*y, 0.26*x + 0.24*y + 0.44; else nx,ny= 0.85*x + 0.04*y, -0.04*x + 0.85*y + 1.6; x,y=nx,ny; bitmap[w/2 + x*60, y*60] = 0x00|FF|00; // Green dot } bitmap.writeJPGFile("barnsleyFern.jpg");
}();</lang>