
// PlasmaCloud.java
// Robert Sedgewick and Kevin Wayne
// Slightly reformatted by Andrew Davison, Nov. 2022

// https://introcs.cs.princeton.edu/java/23recursion/PlasmaCloud.java.html

/* Create a plasma fractal using the midpoint displacement method.
   Also called a fractal cloud. Try different colors to get a cloud.
   Also used to generate random terrain where "color" becomes the
   altitude.
 
   It's possible that the color c does not stay between 0 and 1;
   this is not disastrous since the HSB color routine uses only
   the fractional part
    -book verison is 750-by-400

   Usage:
     > compile PlasmaCloud.java
     > run PlasmaCloud
*/

import java.util.Random;
import java.awt.Color;


public class PlasmaCloud 
{
  private static Random rand = new Random();

  public static void main(String[] args) 
  {
    // choose intial corner colors at random betwen 0 and 1
    double c1 = rand.nextDouble();
    double c2 = rand.nextDouble();
    double c3 = rand.nextDouble();
    double c4 = rand.nextDouble();

    double stddev = 1.0;    // controls variation in color
    plasma(0.5, 0.5, 0.5, stddev, c1, c2, c3, c4);

    System.out.println("Rendering completed");
  } // end of main()


  private static void plasma(double x, double y,  
                             double size, double stddev,
               double c1, double c2, double c3, double c4) 
  /* centered at (x, y), of given size, using given standard 
    deviation for computing the displacement, and with upper left, 
    upper right, lower lower, and lower right hues c1, c2, c3, c4
  */
  {
    if (size <= 0.001)       // base case
      return;

    // calculate new color of midpoint using random displacement
    double displacement = rand.nextDouble()*stddev;
    double cM = (c1+c2+c3+c4)/4.0 + displacement;

    // draw a colored square
    Color color = Color.getHSBColor((float) cM, 0.8f, 0.8f);
    StdDraw.setPenColor(color);
    StdDraw.filledSquare(x, y, size);

    double cT = (c1+c2)/2.0;   // top
    double cB = (c3+c4)/2.0;   // bottom
    double cL = (c1+c3)/2.0;   // left
    double cR = (c2+c4)/2.0;   // right

    plasma(x-size/2, y-size/2, size/2, stddev/2, cL, cM, c3, cB);
    plasma(x+size/2, y-size/2, size/2, stddev/2, cM, cR, cB, c4);
    plasma(x-size/2, y+size/2, size/2, stddev/2, c1, cT, cL, cM);
    plasma(x+size/2, y+size/2, size/2, stddev/2, cT, c2, cM, cR);
  }  // end of plasma()

} // end of PlasmaCloud class
