Barnsley fern

From Rosetta Code
Revision as of 17:51, 1 March 2016 by rosettacode>Fwend (remove vandalism ;-))
Barnsley fern is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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


Java

Works with: Java version 8

<lang java>import java.awt.*; import java.util.ArrayList; import javax.swing.*;

public class BarnsleyFern extends JPanel {

   ArrayList<Point> points = new ArrayList<>();
   public BarnsleyFern() {
       final int dim = 640;
       setPreferredSize(new Dimension(dim, dim));
       setBackground(Color.white);
       setForeground(Color.green.darker());
       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;
           points.add(new Point((int) Math.round(w / 2 + x * 60),
                   (int) Math.round(h - y * 60)));
       }
   }
   void drawFern(Graphics2D g) {
       for (Point p : points) {
           g.fillOval(p.x, p.y, 1, 1);
       }
   }
   @Override
   public void paintComponent(Graphics gg) {
       super.paintComponent(gg);
       Graphics2D g = (Graphics2D) gg;
       g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
       drawFern(g);
   }
   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>

zkl

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Translation of: Java

<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>

Output:

http://www.zenkinetic.com/Images/RosettaCode/barnsleyFern.jpg