/****************************  IFS.java  *************************************/

import java.util.Random;

/**  Iterated Function System zur Erzeugung eines fraktalen Farns */


public class IFS {

  final static double [][][][] a = {              // affine Abbildungen 
     {{{ 0.85,  0.04}, {-0.04, 0.85}},            // fuer Farn 
      {{ 0.20, -0.26}, { 0.23, 0.22}},
      {{-0.15,  0.28}, { 0.26, 0.24}},
      {{ 0.00,  0.00}, { 0.00, 0.16}}}, 

     {{{0.5,  0.0}, {0.0,  0.5}},                 // fuer Sierpinski  
      {{0.5,  0.0}, {0.0,  0.5}},
      {{0.5,  0.0}, {0.0,  0.5}}},

     {{{0.49, 0.01}, {0.0, 0.62}},                // fuer Blatt
      {{0.27, 0.52}, {-0.40, 0.36}},
      {{0.18, -0.73}, {0.50, 0.26}},
      {{0.04, -0.01}, {0.50, 0.0}}}

  };

  final static double [][][] b = {                // Translationsvektoren
        {{0.0, 10.6 },                            // fuer Farn 
         {0.0, 10.6},
         {0.0,  4.4 },
         {0.0,  0.0 }},

        {{0.0, 0.0},                              // fuer Sierpinski
         {50.0, 0.0},
         {0.0, 50.0}} ,

        {{25.0, 2.0},                             // fuer Ahorn-Blatt
         { 0.0, 56.0},
         {88.0, 8.0},
         {52.0, 32.0}}
  };


  final static int [][] prob = {                  // Regelwahrscheinlichkeiten
        {85, 7, 7, 1},                            // fuer Farn                
        {33, 33, 34},                             // fuer Sierpinski
        {25, 25, 25, 25}                          // fuer Ahorn-Blatt
  };


  static Random r = new Random((long)42);
  
  public static int wuerfel(int sys) {            // wuerfelt eine Regel gemaess
                                                  // ihrer Wahrscheinlichkeit
    int k, sum;
    int w  = r.nextInt() % 100; 
    w = w < 0 ? 1-w : 1+w;                        // 1 <= w <= 100 

    sum = prob[sys][0]; k = 0;
    while (sum < w) sum +=prob[sys][++k];
    return k;
  }

  public static void transform ( Punkt p, int sys )  // transformiere Punkt p 
  { 
    int k;
    double x, y;
      
    k = wuerfel(sys);                                 // wuerfel eine Regel
 
    x = a[sys][k][0][0]*p.x +a[sys][k][0][1]*p.y + b[sys][k][0]; // bestimme 
    y = a[sys][k][1][0]*p.x +a[sys][k][1][1]*p.y + b[sys][k][1]; // neuen Punkt
    p.x = x;
    p.y = y; 
  }

}