Advertisement
Guest User

Fractals

a guest
Mar 3rd, 2017
522
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.74 KB | None | 0 0
  1. import java.util.List;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.Random;
  8. import java.nio.file.Files;
  9. import java.nio.file.Path;
  10. import java.nio.file.Paths;
  11. import javax.imageio.ImageIO;
  12. import java.awt.Color;
  13. import java.awt.Graphics2D;
  14. import java.awt.Rectangle;
  15. import java.awt.image.BufferedImage;
  16. import java.io.IOException;
  17.  
  18. public class CartesianPoint {
  19.     public final double X;
  20.     public final double Y;
  21.  
  22.     public CartesianPoint(double X, double Y) {
  23.         this.X = X;
  24.         this.Y = Y;
  25.     }
  26.  
  27.     @Override
  28.     public String toString() {
  29.         return String.format("(%f, %f)", X, Y);
  30.     }
  31. }
  32.  
  33. public class ScreenPoint {
  34.     public final int X;
  35.     public final int Y;
  36.  
  37.     public ScreenPoint(int X, int Y) {
  38.         this.X = X;
  39.         this.Y = Y;
  40.     }
  41.  
  42.     @Override
  43.     public String toString() {
  44.         return String.format("(%d, %d", X, Y);
  45.     }
  46. }
  47.  
  48. public class Coefficients {
  49.     public final double a;
  50.     public final double b;
  51.     public final double c;
  52.     public final double d;
  53.     public final double e;
  54.     public final double f;
  55.  
  56.     public Coefficients(double a, double b, double c, double d, double e, double f) {
  57.         this.a = a;
  58.         this.b = b;
  59.         this.c = c;
  60.         this.d = d;
  61.         this.e = e;
  62.         this.f = f;
  63.     }
  64.  
  65.     public Coefficients(String[] arr) {
  66.         if (arr.length != 6) {
  67.             throw new IllegalArgumentException("Expected arguments: 6. Found: " + arr.length);
  68.         }
  69.         double[] temp = new double[6];
  70.         for (int i = 0; i < 6; i++) {
  71.             temp[i] = Double.parseDouble(arr[i]);
  72.         }
  73.         this.a = temp[0];
  74.         this.b = temp[1];
  75.         this.c = temp[2];
  76.         this.d = temp[3];
  77.         this.e = temp[4];
  78.         this.f = temp[5];
  79.     }
  80.  
  81.     public CartesianPoint translate(CartesianPoint cpoint) {
  82.         double x = cpoint.X, y = cpoint.Y;
  83.         return new CartesianPoint(a*x + b*y + e, c*x + d*y + f);
  84.     }
  85. }
  86.  
  87. public class Utils {
  88.     private static final Random RANDOM = new Random();
  89.  
  90.     public static WeightedRandomizer<Coefficients> parseInput(List<String> rawData) {
  91.         List<String[]> arr_list = new ArrayList<>();
  92.         for (String r : rawData) {
  93.             if (r.isEmpty()) {
  94.                 continue;
  95.             }
  96.             arr_list.add(r.trim().split("\\s+"));
  97.         }
  98.         Map<Coefficients, Double> map = new HashMap<>();
  99.         int len = arr_list.get(0).length;
  100.         for (String[] arr : arr_list) {
  101.             int cur_len = arr.length;
  102.             if (cur_len != 6 && cur_len != 7) {
  103.                 throw new IllegalArgumentException("All coefficients sets need to be of length 6 or 7");
  104.             }
  105.             if (cur_len != len) {
  106.                 throw new IllegalArgumentException("Inconsistent number of coefficients in each set");
  107.             }
  108.             if (cur_len == 6) {
  109.                 map.put(new Coefficients(arr), 1.0);
  110.             } else {
  111.                 map.put(new Coefficients(Arrays.copyOfRange(arr, 0, 6)), Double.parseDouble(arr[6]));
  112.             }
  113.         }
  114.         return new WeightedRandomizer<>(map);
  115.     }
  116.  
  117.     public static List<ScreenPoint> translatePoints(List<CartesianPoint> points, int width, int height) {
  118.         CartesianPoint first = points.get(0);
  119.         double min_x = first.X, max_x = first.X;
  120.         double min_y = first.Y, max_y = first.Y;
  121.         for (CartesianPoint point : points) {
  122.             double x = point.X, y = point.Y;
  123.             if (x < min_x)
  124.                 min_x = x;
  125.             if (x > max_x)
  126.                 max_x = x;
  127.             if (y < min_y)
  128.                 min_y = y;
  129.             if (y > max_y) {
  130.                 max_y = y;
  131.             }
  132.         }
  133.         double dx = max_x - min_x, dy = max_y - min_y;
  134.         List<ScreenPoint> result = new ArrayList<>();
  135.         for (CartesianPoint point : points) {
  136.             int sx = (int)(width * (point.X - min_x) / dx);
  137.             int sy = (int)(height * (max_y - point.Y) / dy);
  138.             result.add(new ScreenPoint(sx, sy));
  139.         }
  140.         return result;
  141.     }
  142.  
  143.     public static List<CartesianPoint> generatePoints(CartesianPoint startingPoint,
  144.                                                       int numOfPoints, int skipFirst,
  145.                                                       WeightedRandomizer<Coefficients> randomizer) {
  146.  
  147.         List<CartesianPoint> result = new ArrayList<>();
  148.         for (int i = 0; i < skipFirst; i++) {
  149.             startingPoint = randomizer.choice().translate(startingPoint);
  150.         }
  151.         for (int i = 0, end = numOfPoints - skipFirst; i < end; i++) {
  152.             startingPoint = randomizer.choice().translate(startingPoint);
  153.             result.add(startingPoint);
  154.         }
  155.         return result;
  156.     }
  157.  
  158.     public static List<CartesianPoint> generatePoints(int numOfPoints, int skipFirst,
  159.                                                       WeightedRandomizer<Coefficients> randomizer) {
  160.         return generatePoints(new CartesianPoint(1, 1), numOfPoints, skipFirst, randomizer);
  161.     }
  162.  
  163.     public static int randomColor() {
  164.         return RANDOM.nextInt(16777216) - 16777216;
  165.     }
  166. }
  167.  
  168. public class WeightedRandomizer <T> {
  169.     private Set<Map.Entry<T, Double>> lookup;
  170.     private double total = 0;
  171.  
  172.     public WeightedRandomizer(Map<T, Double> map) {
  173.         Map<T, Double> tempMap = new HashMap<>();
  174.         for (Map.Entry<T, Double> entry : map.entrySet()) {
  175.             total += entry.getValue();
  176.             tempMap.put(entry.getKey(), total);
  177.         }
  178.         this.lookup = tempMap.entrySet();
  179.     }
  180.  
  181.     public T choice() {
  182.         double r = Math.random() * total;
  183.         for (Map.Entry<T, Double> entry : this.lookup) {
  184.             if (entry.getValue() > r) {
  185.                 return entry.getKey();
  186.             }
  187.         }
  188.         throw new IllegalArgumentException();
  189.     }
  190. }
  191.  
  192. public class IFSImageBuilder {
  193.     private final double PHI = 1.618033988749895;
  194.  
  195.     private Path coefficientsPath;
  196.     private Path savePath;
  197.     private Integer width;
  198.     private Integer height;
  199.     private Integer numberOfPixels;
  200.     private Integer borderSize;
  201.     private Integer skipFirst;
  202.     private Color fractalColor = Color.BLACK;
  203.     private Color backgroundColor = Color.WHITE;
  204.     private boolean timing = true;
  205.     private boolean rainbow = false;
  206.  
  207.     public IFSImageBuilder setCoefficientsPath(Path coefficientsPath) {
  208.         this.coefficientsPath = coefficientsPath;
  209.         return this;
  210.     }
  211.  
  212.     public IFSImageBuilder setCoefficientsPath(String coefficientsPath) {
  213.         setCoefficientsPath(Paths.get(coefficientsPath));
  214.         return this;
  215.     }
  216.  
  217.     public IFSImageBuilder setSavePath(Path savePath) {
  218.         this.savePath = savePath;
  219.         return this;
  220.     }
  221.  
  222.     public IFSImageBuilder setSavePath(String savePath) {
  223.         setSavePath(Paths.get(savePath));
  224.         return this;
  225.     }
  226.  
  227.     public IFSImageBuilder setWidth(Integer width) {
  228.         this.width = width;
  229.         return this;
  230.     }
  231.  
  232.     public IFSImageBuilder setHeight(Integer height) {
  233.         this.height = height;
  234.         return this;
  235.     }
  236.  
  237.     public IFSImageBuilder setNumberOfPixels(Integer numberOfPixels) {
  238.         this.numberOfPixels = numberOfPixels;
  239.         return this;
  240.     }
  241.  
  242.     public IFSImageBuilder setBorderSize(Integer borderSize) {
  243.         this.borderSize = borderSize;
  244.         return this;
  245.     }
  246.  
  247.     public IFSImageBuilder setSkipFirst(Integer skipFirst) {
  248.         this.skipFirst = skipFirst;
  249.         return this;
  250.     }
  251.  
  252.     public IFSImageBuilder setFractalColor(Color fractalColor) {
  253.         this.fractalColor = fractalColor;
  254.         this.rainbow = false;
  255.         return this;
  256.     }
  257.  
  258.     public IFSImageBuilder setBackgroundColor(Color backgroundColor) {
  259.         this.backgroundColor = backgroundColor;
  260.         return this;
  261.     }
  262.  
  263.     public IFSImageBuilder setTiming(boolean timing) {
  264.         this.timing = timing;
  265.         return this;
  266.     }
  267.  
  268.     public IFSImageBuilder setRainbow(boolean rainbow) {
  269.         this.rainbow = rainbow;
  270.         return this;
  271.     }
  272.  
  273.     public IFSImage build() {
  274.         if (width == null && height == null) {
  275.             throw new IllegalArgumentException("Missing of the following: width, height");
  276.         }
  277.         if (width == null) {
  278.             width = (int)(height * PHI);
  279.         } else if (height == null) {
  280.             height = (int)(width * PHI);
  281.         }
  282.         if (numberOfPixels == null) {
  283.             numberOfPixels = width * height;
  284.         }
  285.         if (borderSize == null) {
  286.             borderSize = (int)(0.05 * Math.min(width, height));
  287.         }
  288.         if (skipFirst == null) {
  289.             skipFirst = (int)(0.005 * numberOfPixels);
  290.         }
  291.         return new IFSImage(coefficientsPath, width, height, borderSize, numberOfPixels, skipFirst,
  292.                 fractalColor, backgroundColor, savePath, timing, rainbow);
  293.     }
  294. }
  295.  
  296. public class IFSImage {
  297.     private IFSImage() { }
  298.  
  299.     private Path coefficientsPath;
  300.     private Path savePath;
  301.     private int width;
  302.     private int height;
  303.     private int borderSize;
  304.     private int numberOfPixels;
  305.     private int skipFirst;
  306.     private Color fractalColor;
  307.     private Color backgroundColor;
  308.     private boolean timing;
  309.     private boolean rainbow;
  310.  
  311.     public IFSImage(Path coefficientsPath, int width, int height, int borderSize,
  312.                     int numberOfPixels, int skipFirst,
  313.                     Color fractalColor, Color backgroundColor,
  314.                     Path savePath, boolean timing, boolean rainbow) {
  315.  
  316.         this.coefficientsPath = coefficientsPath;
  317.         this.width = width;
  318.         this.height = height;
  319.         this.borderSize = borderSize;
  320.         this.numberOfPixels = numberOfPixels;
  321.         this.skipFirst = skipFirst;
  322.         this.fractalColor = fractalColor;
  323.         this.backgroundColor = backgroundColor;
  324.         this.savePath = savePath;
  325.         this.timing = timing;
  326.         this.rainbow = rainbow;
  327.     }
  328.  
  329.     public void save() throws IOException {
  330.         long start = 0;
  331.         if (timing) {
  332.             start = System.nanoTime();
  333.         }
  334.  
  335.         int img_width = width + 2*borderSize;
  336.         int img_height = height + 2*borderSize;
  337.  
  338.         BufferedImage img = new BufferedImage(img_width, img_height, BufferedImage.TYPE_INT_RGB);
  339.  
  340.         if (!backgroundColor.equals(Color.BLACK)) {
  341.             Graphics2D graphics = img.createGraphics();
  342.             graphics.setColor(backgroundColor);
  343.             graphics.fill(new Rectangle(0, 0, img_width, img_height));
  344.             graphics.dispose();
  345.         }
  346.  
  347.         List<String> rawData = Files.readAllLines(coefficientsPath);
  348.         WeightedRandomizer<Coefficients> randomizer = Utils.parseInput(rawData);
  349.         List<CartesianPoint> cartesianPoints = Utils.generatePoints(numberOfPixels, skipFirst, randomizer);
  350.         List<ScreenPoint> screenPoints = Utils.translatePoints(cartesianPoints, width, height);
  351.  
  352.         if (rainbow) {
  353.             for (ScreenPoint point : screenPoints) {
  354.                 int color = Utils.randomColor();
  355.                     img.setRGB(point.X + borderSize, point.Y + borderSize, color);
  356.             }
  357.         }
  358.         else {
  359.             int fractalColor_int = fractalColor.getRGB();
  360.             for (ScreenPoint point : screenPoints) {
  361.                 img.setRGB(point.X + borderSize, point.Y + borderSize, fractalColor_int);
  362.             }
  363.         }
  364.  
  365.         ImageIO.write(img, "png", savePath.toFile());
  366.  
  367.         if (timing) {
  368.             double total = (double)(System.nanoTime() - start) / 1e9;
  369.             System.out.printf("Fractal generated in %.4f s", total);
  370.         }
  371.     }
  372. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement