diff --git a/src/main/java/fr/univamu/App.java b/src/main/java/fr/univamu/App.java index 34dbeff7e819051d563bd508684188c036ffc7a7..37538ea0b1d2d08168b10ba31f4851ae45fc5aca 100644 --- a/src/main/java/fr/univamu/App.java +++ b/src/main/java/fr/univamu/App.java @@ -1,6 +1,9 @@ package fr.univamu; +import fr.univamu.geo.Disc; import fr.univamu.geo.Shape; +import fr.univamu.geo.Star; +import fr.univamu.geo.Vector2D; import fr.univamu.svg.SvgElement; import java.io.FileNotFoundException; @@ -26,6 +29,6 @@ public class App { } public static void main(String[] args) throws FileNotFoundException { - // write(new Circle(1),"out/circle.svg"); + write(new Star(7,3),"out/star.svg"); } } diff --git a/src/main/java/fr/univamu/geo/Arbitrary.java b/src/main/java/fr/univamu/geo/Arbitrary.java new file mode 100644 index 0000000000000000000000000000000000000000..dd12583399b5afc7e9524511d40e3595481fa79d --- /dev/null +++ b/src/main/java/fr/univamu/geo/Arbitrary.java @@ -0,0 +1,16 @@ +package fr.univamu.geo; + +import java.util.List; + +public record Arbitrary(List<Vector2D> vertices) implements Polygon { + + @Override + public int nbVertices() { + return vertices.size(); + } + + @Override + public Vector2D getVertex(int index) { + return vertices.get(index); + } +} diff --git a/src/main/java/fr/univamu/geo/Disc.java b/src/main/java/fr/univamu/geo/Disc.java new file mode 100644 index 0000000000000000000000000000000000000000..106b5dba517f4d14a23af7753d062e7f6fbafcea --- /dev/null +++ b/src/main/java/fr/univamu/geo/Disc.java @@ -0,0 +1,16 @@ +package fr.univamu.geo; + +import fr.univamu.svg.SvgElement; + +import static fr.univamu.svg.SvgAttribute.tag; + +public record Disc(double radius, Vector2D center) implements Shape { + + @Override + public SvgElement toSvg() { + return new SvgElement("circle") + .add(tag("r", radius)) + .add(tag("cx", center.x())) + .add(tag("cy", center.y())); + } +} diff --git a/src/main/java/fr/univamu/geo/Polygon.java b/src/main/java/fr/univamu/geo/Polygon.java new file mode 100644 index 0000000000000000000000000000000000000000..fee088372c95296c2cfe2b244163838460a1b490 --- /dev/null +++ b/src/main/java/fr/univamu/geo/Polygon.java @@ -0,0 +1,21 @@ +package fr.univamu.geo; + +import fr.univamu.svg.SvgAttribute; +import fr.univamu.svg.SvgElement; + +public sealed interface Polygon extends Shape + permits Regular, Star, Arbitrary { + + int nbVertices(); + Vector2D getVertex(int index); + + @Override + default SvgElement toSvg() { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < nbVertices(); i++) { + builder.append(getVertex(i)).append(" "); + } + return new SvgElement("polygon") + .add(SvgAttribute.tag("points", builder.toString())); + } +} diff --git a/src/main/java/fr/univamu/geo/Regular.java b/src/main/java/fr/univamu/geo/Regular.java new file mode 100644 index 0000000000000000000000000000000000000000..cbee1fe2cb2759d9e03b472d436fd0cee8fdb437 --- /dev/null +++ b/src/main/java/fr/univamu/geo/Regular.java @@ -0,0 +1,12 @@ +package fr.univamu.geo; + + +public record Regular(int nbVertices) implements Polygon { + + @Override + public Vector2D getVertex(int index) { + return Vector2D.polar(index * 2 * Math.PI / nbVertices(), 1); + } + + +} diff --git a/src/main/java/fr/univamu/geo/Shape.java b/src/main/java/fr/univamu/geo/Shape.java new file mode 100644 index 0000000000000000000000000000000000000000..5b434a1f12aa88d58e5d262aee54b3d244385b3a --- /dev/null +++ b/src/main/java/fr/univamu/geo/Shape.java @@ -0,0 +1,9 @@ +package fr.univamu.geo; + +import fr.univamu.svg.SvgElement; + +public sealed interface Shape + permits Disc, Polygon { + + SvgElement toSvg(); +} diff --git a/src/main/java/fr/univamu/geo/Star.java b/src/main/java/fr/univamu/geo/Star.java new file mode 100644 index 0000000000000000000000000000000000000000..34792ae00811757314fddfd144e552d8f168c380 --- /dev/null +++ b/src/main/java/fr/univamu/geo/Star.java @@ -0,0 +1,11 @@ +package fr.univamu.geo; + + +public record Star(int nbVertices, int step) implements Polygon { + + @Override + public Vector2D getVertex(int index) { + return Vector2D.polar(step * index * 2 * Math.PI / nbVertices(), 1); + } + +} diff --git a/src/main/java/fr/univamu/geo/Vector2D.java b/src/main/java/fr/univamu/geo/Vector2D.java new file mode 100644 index 0000000000000000000000000000000000000000..555fd4075db79dd9ac4606c9ab4f5cebc37efd46 --- /dev/null +++ b/src/main/java/fr/univamu/geo/Vector2D.java @@ -0,0 +1,62 @@ +package fr.univamu.geo; + +public record Vector2D(double x, double y) { + + public static final Vector2D ZERO = new Vector2D(0,0); + public static final Vector2D I = new Vector2D(1,0); + public static final Vector2D J = new Vector2D(0,1); + private static final double EPSILON = 1e-9; + + @Override + public String toString() { + return this.x + "," + this.y; + } + + public static Vector2D cartesian(double x, double y) { + return new Vector2D(x, y); + } + + public static Vector2D polar(double radian, double radius) { + return new Vector2D( + Math.cos(radian) * radius, + Math.sin(radian) * radius + ); + } + + public Vector2D plus(Vector2D vec) { + return new Vector2D(this.x + vec.x, this.y + vec.y); + } + + public Vector2D minus(Vector2D vec) { + return new Vector2D(this.x - vec.x, this.y - vec.y); + } + + public Vector2D opposite() { + return new Vector2D(-this.x, -this.y); + } + + public Vector2D scale(double factor) { + return new Vector2D(factor * this.x, factor * this.y); + } + + public double dot(Vector2D vec) { + return this.x * vec.x + this.y * vec.y; + } + + public Vector2D rotate(double radian) { + return new Vector2D( + Math.cos(radian) * this.x - Math.sin(radian) * this.y, + Math.sin(radian) * this.x + Math.cos(radian) * this.y + ); + } + + @Override + public boolean equals(Object o) { + if (o == this) { return true; } + if (!(o instanceof Vector2D vec)) { + return false; + } + return Math.abs(this.x - vec.x) < EPSILON + && Math.abs(this.y - vec.y) < EPSILON; + } +} diff --git a/src/test/java/fr/univamu/geo/DiscTest.java b/src/test/java/fr/univamu/geo/DiscTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ba1a2bb7d6f25c6fe51c8cc4a183c599337694d0 --- /dev/null +++ b/src/test/java/fr/univamu/geo/DiscTest.java @@ -0,0 +1,18 @@ +package fr.univamu.geo; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class DiscTest { + + @Test + void toSvg() { + assertEquals("<circle r=\"1.0\" cx=\"0.0\" cy=\"0.0\"/>\n", + new Disc(1,Vector2D.ZERO).toSvg().toString() + ); + assertEquals("<circle r=\"0.5\" cx=\"3.0\" cy=\"-2.0\"/>\n", + new Disc(0.5,Vector2D.cartesian(3,-2)).toSvg().toString() + ); + } +} \ No newline at end of file diff --git a/src/test/java/fr/univamu/geo/RegularTest.java b/src/test/java/fr/univamu/geo/RegularTest.java new file mode 100644 index 0000000000000000000000000000000000000000..17be22a2e14669491ff52a42693062e9d1c737fe --- /dev/null +++ b/src/test/java/fr/univamu/geo/RegularTest.java @@ -0,0 +1,18 @@ +package fr.univamu.geo; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class RegularTest { + + @Test + void toSvg() { + assertEquals( + "<polygon points=\"1.0,0.0 -0.4999999999999998,0.8660254037844387 -0.5000000000000004,-0.8660254037844384 \"/>\n" + , new Regular(3).toSvg().toString()); + assertEquals( + "<polygon points=\"1.0,0.0 6.123233995736766E-17,1.0 -1.0,1.2246467991473532E-16 -1.8369701987210297E-16,-1.0 \"/>\n" + , new Regular(4).toSvg().toString()); + } +} \ No newline at end of file diff --git a/src/test/java/fr/univamu/geo/Vector2DTest.java b/src/test/java/fr/univamu/geo/Vector2DTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3dd1fd14987a5f6aca65c2343a626848857428f0 --- /dev/null +++ b/src/test/java/fr/univamu/geo/Vector2DTest.java @@ -0,0 +1,26 @@ +package fr.univamu.geo; + +import org.junit.jupiter.api.Test; + +import static fr.univamu.geo.Vector2D.I; +import static fr.univamu.geo.Vector2D.J; +import static org.junit.jupiter.api.Assertions.*; + +class Vector2DTest { + + @Test + void plus() { + assertEquals(Vector2D.cartesian(1,1), I.plus(J)); + } + + @Test + void minus() { + assertEquals(Vector2D.cartesian(1,-1), I.minus(J)); + } + + @Test + void rotate() { + assertEquals(J, I.rotate(Math.PI/2)); + assertEquals(I, J.rotate(-Math.PI/2)); + } +} \ No newline at end of file