diff --git a/src/main/java/org/example/chaosgame/Main.java b/src/main/java/org/example/chaosgame/Main.java index fc44ddc5b42931e24be0ea4b05db749e6f79c4c4..66b33511806cd6e2e08465a1fbb733ebc15a740d 100644 --- a/src/main/java/org/example/chaosgame/Main.java +++ b/src/main/java/org/example/chaosgame/Main.java @@ -21,7 +21,7 @@ public class Main extends Application { // Change this to the path of the file you want to read description = fileHandler.readFromFile("src/main/resources/barnsley.txt"); } catch (Exception e) { - System.out.println(e);; + System.err.println(e);; } if (description == null) { diff --git a/src/main/java/org/example/chaosgame/chaos/ChaosGameFileHandler.java b/src/main/java/org/example/chaosgame/chaos/ChaosGameFileHandler.java index fa37cade4732046683cc6193a7f4718ced723956..8c955ffbbf2e96869745a9cea9b4d7a432d85c08 100644 --- a/src/main/java/org/example/chaosgame/chaos/ChaosGameFileHandler.java +++ b/src/main/java/org/example/chaosgame/chaos/ChaosGameFileHandler.java @@ -1,5 +1,11 @@ package org.example.chaosgame.chaos; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Scanner; import org.example.chaosgame.linalg.Complex; import org.example.chaosgame.linalg.Matrix2x2; import org.example.chaosgame.linalg.Vector2D; @@ -7,84 +13,128 @@ import org.example.chaosgame.transformations.AffineTransform2D; import org.example.chaosgame.transformations.JuliaTransform; import org.example.chaosgame.transformations.Transform2D; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Locale; -import java.util.Scanner; -import java.util.List; -import java.util.ArrayList; - - +/** + * Class for reading and writing chaos game descriptions from and to files. + */ public class ChaosGameFileHandler { - private Vector2D minCoords; - private Vector2D maxCoords; private final List<Transform2D> transforms = new ArrayList<>(); + /** + * Reads a chaos game description from a file. + * + * <p>The text files should have the following format: + * + * <p>First line: type of transformation (Affine2D or Julia) + * + * <p>Second line: minimum coordinates of the canvas (x, y) + * + * <p>Third line: maximum coordinates of the canvas (x, y) + * + * <p>Fourth line and onwards: the transformations + * + * @param path the path to the file + * @return the chaos game description + * @throws IOException if the file cannot be read + */ public ChaosGameDescription readFromFile(String path) throws IOException { Vector2D minCoords; Vector2D maxCoords; try (Scanner scanner = new Scanner(new File(path))) { scanner.useLocale(Locale.ENGLISH); - String typeOfTransformation = scanner.nextLine(); + + String typeOfTransformation = skipComments(scanner.nextLine()); + System.out.println("Parsing type of transformation: " + typeOfTransformation); + minCoords = parseVector(scanner.nextLine().trim()); maxCoords = parseVector(scanner.nextLine().trim()); - //delimeter for kmt transforms.clear(); + while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (typeOfTransformation.equals("Affine2D")) { - transforms.add(parseAffine(line)); - } else if (typeOfTransformation.equals("Julia")) { - transforms.add(parseJulia(line)); - } else { - throw new IOException("Invalid transform type"); - } + transforms.add(selectTransformation(typeOfTransformation, scanner)); } + } return new ChaosGameDescription(minCoords, maxCoords, transforms); } public void writeToFile(ChaosGameDescription description, String path) throws IOException { - BufferedWriter writer = new BufferedWriter(new FileWriter(path)); - // Skriv type transformasjon - if (description.getTransforms().getFirst() instanceof AffineTransform2D) { - writer.write("Affine2D\n"); - } else if (description.getTransforms().getFirst() instanceof JuliaTransform) { - writer.write("Julia\n"); - } else { - throw new IOException("Invalid transform type"); - } } + /** + * Selects the correct transformation based on the type of transformation. + * + * @param typeOfTransformation a string with the name of the transformation + * @param scanner the scanner to read the transformation from + * @return the transformation + */ + private Transform2D selectTransformation(String typeOfTransformation, Scanner scanner) { + return switch (typeOfTransformation) { + case "Affine2D" -> parseAffine(scanner.nextLine()); + case "Julia" -> parseJulia(scanner.nextLine()); + default -> throw new IllegalArgumentException( + "Unknown type of transformation: " + typeOfTransformation); + }; + } + + /** + * Skips everything after the first # in a line. + * + * @param line a line of text + * @return the first part of the line + */ + private String skipComments(String line) { + String[] parts = line.split("#"); + return parts[0].trim(); + } + + /** + * Parses a vector from a string. + * + * @param line a line of text + * @return the vector + */ private Vector2D parseVector(String line) { - System.out.println("Parsing vector: " + line); - String[] parts = line.split(","); - double x = Double.parseDouble(parts[0].trim()); - double y = Double.parseDouble(parts[1].trim()); + String numbers = skipComments(line); + System.out.println("Parsing vector: " + numbers); + String[] vectorParts = numbers.split(","); + double x = Double.parseDouble(vectorParts[0].trim()); + double y = Double.parseDouble(vectorParts[1].trim()); return new Vector2D(x, y); } + /** + * Parses an affine transformation from a string. + * + * @param line a line of text + * @return the transformation + */ private Transform2D parseAffine(String line) { - System.out.println("Parsing transform: " + line); - String[] parts = line.split(","); - double a = Double.parseDouble(parts[0].trim()); - double b = Double.parseDouble(parts[1].trim()); - double c = Double.parseDouble(parts[2].trim()); - double d = Double.parseDouble(parts[3].trim()); - double x = Double.parseDouble(parts[4].trim()); - double y = Double.parseDouble(parts[5].trim()); + String numbers = skipComments(line); + System.out.println("Parsing transform: " + numbers); + String[] transformParts = numbers.split(","); + double a = Double.parseDouble(transformParts[0].trim()); + double b = Double.parseDouble(transformParts[1].trim()); + double c = Double.parseDouble(transformParts[2].trim()); + double d = Double.parseDouble(transformParts[3].trim()); + double x = Double.parseDouble(transformParts[4].trim()); + double y = Double.parseDouble(transformParts[5].trim()); return new AffineTransform2D(new Matrix2x2(a, b, c, d), new Vector2D(x, y)); } + /** + * Parses a Julia transformation from a string. + * + * @param line a line of text + * @return the transformation + */ private Transform2D parseJulia(String line) { - System.out.println("Parsing transform: " + line); - String[] parts = line.split(","); - double r = Double.parseDouble(parts[0].trim()); - double i = Double.parseDouble(parts[1].trim()); + String numbers = skipComments(line); + System.out.println("Parsing transform: " + numbers); + String[] transformParts = numbers.split(","); + double r = Double.parseDouble(transformParts[0].trim()); + double i = Double.parseDouble(transformParts[1].trim()); return new JuliaTransform(new Complex(r, i), 1); } } diff --git a/src/main/resources/barnsley.txt b/src/main/resources/barnsley.txt index 6985707d20e4faf7b2e3b0959ceccbc4ca6bd632..8810e8694cd1c9124499bbcc1917242f262c3745 100644 --- a/src/main/resources/barnsley.txt +++ b/src/main/resources/barnsley.txt @@ -1,7 +1,7 @@ -Affine2D --2.65, 0 -2.65, 10 -0, 0, 0, .16, 0, 0 -.85, .04, -.04, .85, 0, 1.6 -.2, -.26, .23, .22, 0, 1.6 --.15, .28, .26, .24, 0, .44 \ No newline at end of file +Affine2D # Type of transformation +-2.65, 0 # Min-coordinate +2.65, 10 # Max-coordinate +0, 0, 0, .16, 0, 0 # 1st transform +.85, .04, -.04, .85, 0, 1.6 # 2nd transform +.2, -.26, .23, .22, 0, 1.6 # 3rd transform +-.15, .28, .26, .24, 0, .44 # 4th transform \ No newline at end of file diff --git a/src/main/resources/julia.txt b/src/main/resources/julia.txt index a7d337f38ccf597dbda06083873c6646d99b24fd..118baee3ccbaffae380b35773c494cdc3d3e75e9 100644 --- a/src/main/resources/julia.txt +++ b/src/main/resources/julia.txt @@ -1,4 +1,4 @@ -Julia --1.6, -1 -1.6, 1 --0.70176, -0.3842 \ No newline at end of file +Julia # Type of transformation +-1.6, -1 # Min-coordinates +1.6, 1 # Max-coordinates +-0.70176, -0.3842 # Real and Imaginary part of the constant c \ No newline at end of file diff --git a/src/main/resources/sierpinski.txt b/src/main/resources/sierpinski.txt index fce920799d5566b419a5688a7625690450ff5369..7132287bf61ac6ea7a92a4efa6e3c70203f02ad2 100644 --- a/src/main/resources/sierpinski.txt +++ b/src/main/resources/sierpinski.txt @@ -1,6 +1,6 @@ -Affine2D -0, 0 -1, 1 -.5, 0, 0, .5, 0, 0 -.5, 0, 0, .5, .25, .5 -.5, 0, 0, .5, .5, 0 \ No newline at end of file +Affine2D # Type of transformation +0, 0 # Min-coordinate +1, 1 # Max-coordinate +.5, 0, 0, .5, 0, 0 # 1st transform +.5, 0, 0, .5, .25, .5 # 2nd transform +.5, 0, 0, .5, .5, 0 # 3rd transform \ No newline at end of file