diff --git a/include/box.h b/include/box.h
new file mode 100644
index 0000000000000000000000000000000000000000..57a99adfcbb9a9ca32cedc6b2a3aa4d76ce927f1
--- /dev/null
+++ b/include/box.h
@@ -0,0 +1,6 @@
+#pragma once
+
+struct Box {
+    float minX, maxX, minY, maxY;
+    bool isIn(const Triangle &t) const;
+};
\ No newline at end of file
diff --git a/include/constants.h b/include/constants.h
index 0ec927ff5a50bdc477c466fd376435550bbc613d..553fad2756aeba4a270a1aa8fb85a0ed6ab47663 100644
--- a/include/constants.h
+++ b/include/constants.h
@@ -1,3 +1,5 @@
 #pragma once
 
-#define MAX_TRIANGLE_INTERSECTION_POINTS 12
\ No newline at end of file
+#define MAX_TRIANGLE_INTERSECTION_POINTS 12
+
+#define NB_TRIANGLE_SIDES 3
\ No newline at end of file
diff --git a/include/quad_tree.h b/include/quad_tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9cc89f167a86ad37890ccd6b6bec7efb7a2da99
--- /dev/null
+++ b/include/quad_tree.h
@@ -0,0 +1,31 @@
+#pragma once
+#include <vector>
+#include <triangle.h>
+#include <box.h>
+
+enum Status {
+    Empty,
+    Single,
+    Quad
+};
+
+class QuadTree {
+    Box b;
+    Status status;
+    QuadContent q;
+    public:
+    void addTriangle(const Triangle &t);
+    QuadTree(Box b);
+    std::vector<Triangle> visibleSurface() const;
+    Triangle triangleIntersection(const Point &p) const;
+
+};
+
+union QuadContent {
+
+    Triangle t;
+    std::vector<QuadTree> children;
+    bool nothing;
+    QuadContent() {};
+    ~QuadContent() {};
+};
\ No newline at end of file
diff --git a/include/triangulation.h b/include/triangulation.h
index ef2134e9502f80c5e641b6322305daff62e23295..670cb6f44d43e898e643f9e0526339ad0c034a09 100644
--- a/include/triangulation.h
+++ b/include/triangulation.h
@@ -10,3 +10,4 @@ std::optional<Triangle> removeEar(int &index, PointList &pointList, const std::v
 
 std::vector<Triangle> triangulate(std::vector<Point> points);
 
+std::vector<Triangle> triangulate(Triangle t1, Triangle t2);
\ No newline at end of file
diff --git a/src/data_structures/box.cpp b/src/data_structures/box.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e5d5811252a1193cca20cee413d27a1c8324693
--- /dev/null
+++ b/src/data_structures/box.cpp
@@ -0,0 +1,14 @@
+#include <box.h>
+#include <triangle.h>
+#include <constants.h>
+
+bool Box::isIn(const Triangle &t) const {
+    for (int i = 0; i < NB_TRIANGLE_SIDES; i++) {
+        float x = t.points[i].x;
+        float y = t.points[i].y;
+        if (x > minX && x < maxX && y > minY && y < maxY) {
+            return true;
+        }
+    }
+    return false;
+}
\ No newline at end of file
diff --git a/src/data_structures/quad_tree.cpp b/src/data_structures/quad_tree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dfc77dfa7c6e875d19f3a6d8a62f776c616addbb
--- /dev/null
+++ b/src/data_structures/quad_tree.cpp
@@ -0,0 +1,53 @@
+#include <quad_tree.h>
+
+QuadTree::QuadTree(Box b) : b{b}, status{Empty} {
+    q.nothing = false;
+}
+
+void QuadTree::addTriangle(const Triangle &t)
+{
+    if (!b.isIn(t)) {
+        return;
+    }
+    switch (status)
+    {
+    case Empty:
+        status = Single;
+        q.t = t;
+        break;
+
+    case Single:
+
+        Triangle old = q.t;
+
+        
+        status = Quad;
+        q.children = {
+            QuadTree(Box{b.minX, b.maxX / 2, b.minY, b.maxY}),
+             QuadTree(Box{b.maxX / 2, b.maxX, b.minY, b.maxY / 2}),
+              QuadTree(Box{b.maxX / 2, b.maxX, b.maxY / 2, b.maxY}),
+               QuadTree(Box{b.minX, b.maxX / 2, b.minY, b.maxY / 2})
+            };
+            // if the old and new triangle intersect, we want to avoid infinite additions to the tree.
+            // create new set of triangles that don't intersect
+            std::vector<Triangle> newTriangles = triangulate(old, t);
+        for (int i = 0; i < q.children.size(); i++) {
+            for (int j = 0; j < newTriangles.size(); i++) {
+                q.children[i].addTriangle(newTriangles[i]);
+            }
+        }
+        break;
+    case Quad:
+    for (int i = 0; i < q.children.size(); i++) {
+        addTriangle(t);
+    }
+        break;
+    default:
+        break;
+    }
+}
+
+
+std::vector<Triangle> QuadTree::visibleSurface() const {
+    // for every 
+}
\ No newline at end of file
diff --git a/src/utilities/intersections.cpp b/src/utilities/intersections.cpp
index 8b299f4ce682b917823c375b3723ba9fa83d58ea..b4b0e64be7198437d2f7f6ff4751ee46097c9d79 100644
--- a/src/utilities/intersections.cpp
+++ b/src/utilities/intersections.cpp
@@ -2,6 +2,7 @@
 #include <optional>
 #include <edge.h>
 #include <triangle_edges.h>
+#include <triangle.h>
 
 
 
@@ -30,8 +31,14 @@ bool withinEdge(Edge e, Point p) {
     return minX <= p.x && p.x <= maxX && minY <= p.y && p.y <= maxY; 
 }
 
-
 void intersection(Edge e1, Edge e2, std::vector<Point> &results) {
+    auto point = intersection(e1, e2);
+    if (point.has_value()) {
+        results.push_back(point.value());
+    }
+}
+
+std::optional<Point> intersection(const Edge &e1, const Edge &e2) {
     auto slope1 = getSlope(e1);
     auto slope2 = getSlope(e2);
 
@@ -41,39 +48,38 @@ void intersection(Edge e1, Edge e2, std::vector<Point> &results) {
 
     // ignore overlapping case
     if (!slope1.has_value() && !slope2.has_value()) {
-        return;
+        return {};
     }
 
     if (!slope1.has_value()) {
-        results.push_back(Point{e1.p1.x, slope2.value() * e1.p1.x + b2.value()});
-        return;
+        return Point{e1.p1.x, slope2.value() * e1.p1.x + b2.value()};
     }
 
     if (!slope2.has_value()) {
-        results.push_back(Point{e2.p1.x, slope1.value() * e2.p1.x + b1.value()});
-        return;
+        return Point{e2.p1.x, slope1.value() * e2.p1.x + b1.value()};
     }
     float candX = (b2.value() - b1.value()) / (slope1.value() - slope2.value());
     auto candPoint = Point{ candX, slope1.value() * candX + b1.value()};
 
     if (withinEdge(e1, candPoint) && withinEdge(e2, candPoint)) {
-        results.push_back(candPoint);
+        return candPoint;
     }
 }
-void intersections(Edge e1, TriangleEdges te, std::vector<Point> &results) {
-   intersection(e1, te.e1, results);
-   intersection(e1, te.e2, results);
-   intersection(e1, te.e3, results); 
+void intersections(const Edge &e1, const TriangleEdges &te, std::vector<Point> &results) {
+    for (int i = 0; i < NB_TRIANGLE_SIDES; i++) {
+        intersection(e1, te.edges[i], results);
+    }
 }
-std::vector<Point> intersections(Triangle t1, Triangle t2) {
+std::vector<Point> intersections(const Triangle &t1, const Triangle &t2) {
     TriangleEdges t1Edges = TriangleEdges(t1);
 
     TriangleEdges t2Edges = TriangleEdges(t2);
     std::vector<Point> results;
 
-    intersections(t1Edges.e1, t2Edges, results);
-    intersections(t1Edges.e2, t2Edges, results);
-    intersections(t1Edges.e3, t2Edges, results);
+    for (int i = 0; i < NB_TRIANGLE_SIDES; i++) {
+    intersections(t1Edges.edges[i], t2Edges, results);
+    }
+
 
     return results;
 }