Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.ignatieff.rei;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.awt.Point;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.regex.Pattern;
- import javax.imageio.ImageIO;
- public class Generator {
- public static String TRIANGLE_FRACTAL = "(1+2+3)*0(1+3)*0(0+1+2+3)*";
- private int resolution, size;
- private Color WHITE = Color.white, BLACK = Color.black;
- /**
- * Creates a new generator with as a high a resolution as possible.
- * @param size The width / height of the image to create. This variable must be a power of 2.
- */
- public Generator(int size){
- this((int)log2(size), size);
- }
- /**
- * Creates new generator, for creating images based on regular expresions.
- * Keep in mind that the size needs to be a power of 2, for this to work properly.
- * If 'size' is not a power of 2, it'll be converted to the closest power of 2 relative to 'size.
- *
- * Also note that 'resolution' cannot exceed log2(size). If 'resolution' is higher than log2(size) it'll be changed to log2(size).
- *
- * @param resolution The resolution of the images to create. Higher resolution results in better image quality, but longer render time.
- * @param size The width / height of the image to create. This variable must be a power of 2.
- */
- public Generator(int resolution, int size){
- this.resolution = resolution;
- this.size = size;
- if(!isPow2(size)){
- this.size = (int)Math.pow(2, Math.round(log2(size)));
- System.out.println("Error: size is not a power of 2, changing size to '"+this.size+"'.");
- }
- if(Math.pow(2,resolution)>size){
- this.resolution = (int)log2(this.size);
- System.out.println("Error: resolution too large, changing resolution to '"+this.resolution+"'.");
- }
- }
- private static char[] regExps = "!$%^&*_+|~-=`(){}[]:\";'<>?,./".toCharArray();
- private static char[] valids = "!$%^&*_+|~-=`(){}[]:\";'<>?,./0123".toCharArray();
- /**
- * Checks whether or not a character is a regular expression-symbol or a character.
- * @param c The character to check.
- * @return True, if it's a regular expression symbol, false if it's a character.
- */
- private static boolean isRegExp(char c){
- for(char k : regExps){
- if(k==c)return true;
- }
- return false;
- }
- /**
- * Will evaluate whether a regular expression is valid for this generator or not.
- * @param regex The regex to evaluate.
- * @return True, it it's valid. False, if it's invalid.
- */
- private static boolean isValid(String regex){
- char[] chars = regex.toCharArray();
- for(char c : chars){
- boolean valid = false;
- for(char k : valids){
- if(k==c){
- valid=true;
- break;
- }
- }
- if(!valid)return false;
- }
- return true;
- }
- /*public static String getRegexFromImage(BufferedImage img){
- }*/
- /**
- * Will clean an arbitrary regular expression, making it available to use for generating images,
- * even though it was created for a different purpose.
- *
- * It works by mapping all the non-regular expression symbols (+, [, ], *) unto the characters 0, 1, 2, 3.
- * @param regex The regular expression to clean.
- * @return A cleaned regular expression.
- */
- private static String cleanRegEx(String regex){
- if(isValid(regex))return regex;
- int i = 0;
- Map<Character, Integer> map = new HashMap<Character, Integer>();
- char[] regs = regex.toCharArray();
- char[] clean = new char[regs.length];
- for(char c : regs){
- if(map.containsKey(c))continue;
- if(isRegExp(c))continue;
- map.put(c, i);
- i = (i + 1) % 4;
- }
- for(int j=0; j<regs.length; j++){
- if(map.containsKey(regs[j])){
- clean[j] = Integer.toString(map.get(regs[j])).charAt(0);
- continue;
- }
- clean[j] = regs[j];
- }
- System.out.println(new String(clean));
- return new String(clean);
- }
- /**
- * Returns log2 of a double. Uses the identity log_b(x) = ln(x)/ln(b)
- * @param d The double to get the log2 of.
- * @return log2(d)
- */
- private static double log2(double d){
- return Math.log(d)/Math.log(2);
- }
- /**
- * Checks whether an integer is a power of 2.
- * @param k The integer to perform the check on
- * @return True if the integer is a power of 2, false otherwise.
- */
- private static boolean isPow2(int k){
- return (Math.pow(2, Math.floor(log2(k))) == k);
- }
- /**
- * Will change all (,{,< to [ and all ),},> to ] because Java thinks they are characters, not symbols.
- * @param s
- * @return
- */
- private static String removeParentheses(String s){
- return s.replace("(", "[")
- .replace(")", "]")
- .replace("{", "[")
- .replace("}", "]")
- .replace("<", "[")
- .replace(">", "]");
- }
- /**
- * Generate an image from a regular expressions and save it to the file system.
- * @param regex The regular expression to use for generating the image.
- * @param path The relative path to save the image to.
- */
- public void generateAndExport(String regex, String path){
- try {
- BufferedImage img = generate(regex);
- ImageIO.write(img, "png", new File(path));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * Generate an image from a regular expression and return it as a BufferedImage.
- * @param regex The regular expression to use for generating the image.
- * @return The image generated as a BufferedImage.
- */
- public BufferedImage generate(String regex){
- return generate(
- Pattern.compile(
- cleanRegEx(
- removeParentheses(regex))));
- }
- /**
- * Generate an image from a regular expression and return it as a BufferedImage.
- * @param p The regular expression as a 'Pattern' to use for generating the image.
- * If you're confused, just parse a string instead, it'll be handled anyway.
- * @return The image generated as a BufferedImage.
- */
- public BufferedImage generate(Pattern p){
- BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
- Graphics g = img.createGraphics();
- g.setColor(WHITE);
- g.fillRect(0, 0, size, size);
- g.setColor(BLACK);
- int pointSize = (int) ((int) size/Math.pow(2, resolution));
- String[] s = getAllStrings();
- for(String q : s){
- if(!p.matcher(q).matches())continue;
- Point x = stringToPoint(q, size);
- g.fillRect(x.x, x.y, pointSize, pointSize);
- }
- return img;
- }
- /**
- * Pads a string with 0's to ensure that all strings are of equal length.
- * @param s The string to pad.
- * @param length The length the string must match.
- * @return A padded version of 's' with length 'length'.
- */
- private String pad(String s, int length){
- StringBuilder sb = new StringBuilder();
- int dx = length - s.length();
- for(int i=0; i<dx; i++){
- sb.append("0");
- }
- sb.append(s);
- return sb.toString();
- }
- /**
- * Gets all strings of length 'size'. Depends on the generator.
- * @return All strings of length 'size'.
- */
- private String[] getAllStrings(){
- int max = (int) Math.pow(4, resolution);
- String[] strings = new String[max];
- for(int i=0; i<max; i++){
- strings[i] = pad(Integer.toString(i, 4), resolution);
- }
- return strings;
- }
- /**
- * Gets the relative position of a character, only matches 0, 1, 2, 3.
- *
- * It uses the placement
- *
- * 1 2
- * 0 3
- *
- * @param c The character to get the relative position of.
- * @param size The width / height of the virtual frame.
- * @return A point, representing the virtual position of the character. Will return null if the character isn't valid (0,1,2,3).
- */
- private static Point charToPoint(char c, int size){
- int x = size/2;
- switch(c){
- case '0':
- return new Point(0, x);
- case '1':
- return new Point(0, 0);
- case '2':
- return new Point(x, 0);
- case '3':
- return new Point(x, x);
- }
- return null;
- }
- /**
- * Recursive function for finding the position (x,y) of a string.
- * @param s The string to get the position of.
- * @param size The width / height of the frame.
- * @return A point representing the position of the string.
- */
- private static Point stringToPoint(String s, int size){
- if(s.length() == 1){
- return charToPoint(s.charAt(0), size);
- }
- Point p = charToPoint(s.charAt(0), size);
- Point q = stringToPoint(s.substring(1), size/2);
- return new Point(p.x + q.x, p.y + q.y);
- }
- private static double decreaseAmount = 0.75;
- private static double[] probs = {0.333, 0.333, 0.333};
- /**
- * Generate a random regular expression.
- * @param x The 'length' of the expression.
- * @return A random regular expression.
- */
- public static String randomRegExp(double x){
- double newX = x * decreaseAmount;
- double s = Math.random();
- if(s <= probs[0]*x){
- return randomRegExp(newX) + "+" + randomRegExp(newX);
- }
- s-= probs[0]*x;
- if(s <= probs[1]*x){
- return "[" + randomRegExp(newX) + "][" + randomRegExp(newX) + "]";
- }
- s-= probs[1]*x;
- if(s <= probs[2]*x){
- return "[" + randomRegExp(newX) + "]*";
- }
- return Integer.toString((int)Math.floor(4*Math.random()));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement