Barnsley fern: Difference between revisions
(added Delphi) |
(→{{header|Perl}}: adding PARI/GP script) |
||
Line 320: | Line 320: | ||
} |
} |
||
}</lang> |
}</lang> |
||
=={{header|PARI/GP}}== |
|||
{{trans|zkl}} |
|||
{{Works with|PARI/GP|2.7.4 and above}} |
|||
[[File:BarnsleyFern.png|right|thumb|Output BarnsleyFern.png]] |
|||
<lang parigp> |
|||
\\ Barnsley fern fractal |
|||
\\ 6/17/16 aev |
|||
pBarnsleyFern(size,lim)={ |
|||
my(X=List(),Y=X,x=y=xw=yw=0.0,r); |
|||
print(" *** Barnsley Fern, size=",size," lim=",lim); |
|||
plotinit(0); plotcolor(0,6); \\green |
|||
plotscale(0, -3,3, 0,10); plotmove(0, 0,0); |
|||
for(i=1, lim, |
|||
r=random(100); |
|||
if(r<=1, xw=0;yw=0.16*y, |
|||
if(r<=8, xw=0.2*x-0.26*y;yw=0.23*x+0.22*y+1.6, |
|||
if(r<=15, xw=-0.15*x+0.28*y;yw=0.26*x+0.24*y+0.44, |
|||
xw=0.85*x+0.04*y;yw=-0.04*x+0.85*y+1.6))); |
|||
x=xw;y=yw; listput(X,x); listput(Y,y); |
|||
);\\fend i |
|||
plotpoints(0,Vec(X),Vec(Y)); |
|||
plotdraw([0,-3,-0]); |
|||
} |
|||
{\\ Executing: |
|||
pBarnsleyFern(530,100000); \\ BarnsleyFern.png |
|||
} |
|||
</lang> |
|||
{{Output}} |
|||
<pre> |
|||
> pBarnsleyFern(530,100000); \\ BarnsleyFern.png |
|||
*** Barnsley Fern, size=530 lim=100000 |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
Revision as of 23:55, 19 June 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>
Delphi
Hint: After putting a TPaintBox on the main form align it to alClient. Client width / heigth of the main form should be no less than 640 x 480. <lang delphi>unit Unit1;
interface
uses
Windows, SysUtils, Graphics, Forms, Controls, Classes, ExtCtrls;
type
TForm1 = class(TForm) PaintBox1: TPaintBox; procedure FormPaint(Sender: TObject); private { Private declarations } public { Public declarations } end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure CreateFern(const w, h: integer); var r, x, y: double;
tmpx, tmpy: double; i: integer;
begin
x := 0; y := 0; randomize();
for i := 0 to 200000 do begin r := random(100000000) / 99999989; if r <= 0.01 then begin tmpx := 0; tmpy := 0.16 * y; end else if r <= 0.08 then begin tmpx := 0.2 * x - 0.26 * y; tmpy := 0.23 * x + 0.22 * y + 1.6; end else if r <= 0.15 then begin tmpx := -0.15 * x + 0.28 * y; tmpy := 0.26 * x + 0.24 * y + 0.44; end else begin tmpx := 0.85 * x + 0.04 * y; tmpy := -0.04 * x + 0.85 * y + 1.6; end; x := tmpx; y := tmpy;
Form1.PaintBox1.Canvas.Pixels[round(w / 2 + x * w / 11), round(h - y * h / 11)] := clGreen; end;
end;
procedure TForm1.FormPaint(Sender: TObject); begin
CreateFern(Form1.ClientWidth, Form1.ClientHeight);
end;
end.</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>
PARI/GP
<lang parigp> \\ Barnsley fern fractal \\ 6/17/16 aev pBarnsleyFern(size,lim)={ my(X=List(),Y=X,x=y=xw=yw=0.0,r); print(" *** Barnsley Fern, size=",size," lim=",lim); plotinit(0); plotcolor(0,6); \\green plotscale(0, -3,3, 0,10); plotmove(0, 0,0); for(i=1, lim,
r=random(100); if(r<=1, xw=0;yw=0.16*y, if(r<=8, xw=0.2*x-0.26*y;yw=0.23*x+0.22*y+1.6, if(r<=15, xw=-0.15*x+0.28*y;yw=0.26*x+0.24*y+0.44, xw=0.85*x+0.04*y;yw=-0.04*x+0.85*y+1.6))); x=xw;y=yw; listput(X,x); listput(Y,y);
);\\fend i plotpoints(0,Vec(X),Vec(Y)); plotdraw([0,-3,-0]); } {\\ Executing: pBarnsleyFern(530,100000); \\ BarnsleyFern.png } </lang>
- Output:
> pBarnsleyFern(530,100000); \\ BarnsleyFern.png *** Barnsley Fern, size=530 lim=100000
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>
Ring
<lang Ring>
Load "guilib.ring"
/*
+--------------------------------------------------------------------------- + Program Name : Draw Barnsley Fern + Date : 2016.06.12 + Author : Bert Mariani + Purpose : Draw Fern using Quadratic Equation and Random Number +---------------------------------------------------------------------------
- /
- -------------------------------
- DRAW CHART size 400 x 500
- -------------------------------
New qapp {
win1 = new qwidget() {
### Position and Size on Screen
setwindowtitle("Drawing using QPainter")
setgeometry( 10, 25, 400, 500)
### Draw within this Win Box label1 = new qlabel(win1) { ### Label Position and Size setgeometry(10, 10, 400, 500) settext(" ") }
buttonFern = new qpushbutton(win1) { ### Button DrawFern setgeometry(10, 10, 80, 20) settext("Draw Fern") setclickevent("DrawFern()") ### Call DRAW function }
show() } exec() }
- ------------------------
- FUNCTIONS
- ------------------------
Func DrawFern p1 = new qpicture()
colorGreen = new qcolor() { setrgb(0,255,0,255) } penGreen = new qpen() { setcolor(colorGreen) setwidth(1) }
new qpainter() { begin(p1) setpen(penGreen)
###------------------------------------- ### Quadratic equation matrix of arrays
a = [ 0, 0.85, 0.2, -0.15 ] b = [ 0, 0.04, -0.26, 0.28 ] c = [ 0, -0.04, 0.23, 0.26 ] d = [ 0.16, 0.85, 0.22, 0.24 ] e = [ 0, 0, 0, 0 ] f = [ 0, 1.6, 1.6, 0.44 ]
### Initialize x, y points
xf = 0.0 yf = 0.0
### Size of output screen
MaxX = 400 MaxY = 500 MaxIterations = MaxY * 200 Count = 0
###------------------------------------------------
while ( Count <= MaxIterations )
### NOTE *** RING *** starts at Index 1, ### Do NOT use Random K=0 result
k = random() % 100 k = k +1
### if (k = 0) k = 1 ok ### Do NOT use
if ((k > 0) and (k <= 85)) k = 2 ok if ((k > 85) and (k <= 92)) k = 3 ok if (k > 92) k = 4 ok
TempX = ( a[k] * xf ) + ( b[k] * yf ) + e[k] TempY = ( c[k] * xf ) + ( d[k] * yf ) + f[k]
xf = TempX yf = TempY
if( (Count >= MaxIterations) or (Count != 0) ) xPoint = (floor(xf * MaxY / 11) + floor(MaxX / 2)) yPoint = (floor(yf * -MaxY / 11) + MaxY ) drawpoint( xPoint , yPoint ) ok
Count++ end
###----------------------------------------------------
endpaint() }
label1 { setpicture(p1) show() } return
</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>
ZX Spectrum Basic
<lang zxbasic>10 REM Fractal Fern 20 PAPER 7: BORDER 7: BRIGHT 1: INK 4: CLS 30 LET maxpoints=20000: LET x=0: LET y=0 40 FOR n=1 TO maxpoints 50 LET p=RND*100 60 IF p<=1 THEN LET nx=0: LET ny=0.16*y: GO TO 100 70 IF p<=8 THEN LET nx=0.2*x-0.26*y: LET ny=0.23*x+0.22*y+1.6: GO TO 100 80 IF p<=15 THEN LET nx=-0.15*x+0.28*y: LET ny=0.26*x+0.24*y+0.44: GO TO 100 90 LET nx=0.85*x+0.04*y: LET ny=-0.04*x+0.85*y+1.6 100 LET x=nx: LET y=ny 110 PLOT x*17+127,y*17 120 NEXT n </lang> It is recommended to run on an emulator that supports running at full speed.