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