From 5abb99b59a0a464ca258637fc793c69ba261b840 Mon Sep 17 00:00:00 2001
From: Brandon Lai-Cheong <brandon.lai-cheong@uwaterloo.ca>
Date: Wed, 6 Nov 2024 09:38:07 -0500
Subject: [PATCH] init quadtree

---
 CMakeLists.txt                    |  1 +
 include/box.h                     |  2 ++
 include/constants.h               |  2 +-
 include/quad_tree.h               | 21 +++++++++++++++
 include/triangle.h                |  8 +++---
 src/data_structures/quad_tree.cpp | 44 +++++++++++++++++++++++++++++++
 src/utilities/contourize.cpp      | 27 -------------------
 src/utilities/triangulation.cpp   | 17 +++++-------
 tests/quad_tree_tests.cpp         | 16 +++++++++++
 9 files changed, 97 insertions(+), 41 deletions(-)
 create mode 100644 include/quad_tree.h
 create mode 100644 src/data_structures/quad_tree.cpp
 create mode 100644 tests/quad_tree_tests.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 67b5a53..414230a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,7 @@ add_executable(
 	tests/unit_tests/intersections_tests.cpp
 	src/data_structures/box.cpp
 	src/data_structures/quad_tree.cpp
+	tests/quad_tree_tests.cpp
 )
 
 include_directories(include)
diff --git a/include/box.h b/include/box.h
index 57a99ad..96a894b 100644
--- a/include/box.h
+++ b/include/box.h
@@ -1,5 +1,7 @@
 #pragma once
 
+struct Triangle;
+
 struct Box {
     float minX, maxX, minY, maxY;
     bool isIn(const Triangle &t) const;
diff --git a/include/constants.h b/include/constants.h
index 553fad2..f1f3727 100644
--- a/include/constants.h
+++ b/include/constants.h
@@ -2,4 +2,4 @@
 
 #define MAX_TRIANGLE_INTERSECTION_POINTS 12
 
-#define NB_TRIANGLE_SIDES 3
\ No newline at end of file
+#define NB_TRIANGLE_SIDES 3
diff --git a/include/quad_tree.h b/include/quad_tree.h
new file mode 100644
index 0000000..5081945
--- /dev/null
+++ b/include/quad_tree.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "triangle.h"
+#include <memory>
+#include <vector>
+#include "box.h"
+
+#define QUADTREE_NODE_MAX_SHAPE 4
+
+class QuadTree {
+    Box b;
+    std::shared_ptr<Triangle> t;
+
+    std::vector<QuadTree> children;
+
+    public:
+        QuadTree(Box b);
+        void addTriangle(std::shared_ptr<Triangle> t);
+        std::vector<Triangle> visibleSurface() const;
+        Triangle pointIntersection(Point p) const;
+
+};
\ No newline at end of file
diff --git a/include/triangle.h b/include/triangle.h
index 6aa0498..c1cf50f 100644
--- a/include/triangle.h
+++ b/include/triangle.h
@@ -2,9 +2,11 @@
 #include "point.h"
 
 // points specified counterclockwise
-struct Triangle {
-	Point points[3];
-	int depth;
+struct Triangle
+{
+    Point points[3];
+    int depth;
+    int id;
     bool neighbours(const Triangle &other) const;
     Triangle(Point p1, Point p2, Point p3, int depth);
     bool pointInTriangle(const Point &p) const;
diff --git a/src/data_structures/quad_tree.cpp b/src/data_structures/quad_tree.cpp
new file mode 100644
index 0000000..57c101d
--- /dev/null
+++ b/src/data_structures/quad_tree.cpp
@@ -0,0 +1,44 @@
+#include <quad_tree.h>
+#include <union.h>
+
+QuadTree::QuadTree(Box b) : b{b} {}
+
+void QuadTree::addTriangle(std::shared_ptr<Triangle> t)
+{
+
+    if (!b.isIn(*t))
+    {
+        return;
+    }
+
+    if (this->t == nullptr && children.empty())
+    {
+        this->t = t;
+        return;
+    }
+
+    if (!children.empty())
+    {
+        for (auto &c : children)
+        {
+            c.addTriangle(t);
+        }
+    }
+
+    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})};
+
+    auto newTriangles = unionize(*t, *(this->t));
+    this->t = nullptr;
+
+    for (auto &c : children)
+    {
+        for (auto &newT : newTriangles)
+        {
+            c.addTriangle(std::make_shared<Triangle>(newT));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/utilities/contourize.cpp b/src/utilities/contourize.cpp
index b57d2c7..6252852 100644
--- a/src/utilities/contourize.cpp
+++ b/src/utilities/contourize.cpp
@@ -10,34 +10,7 @@ Triangle clockwiseToCounterclockwise(const Triangle &t)
     return Triangle(t.points[0], t.points[2], t.points[1], t.depth);
 }
 
-/*
-bool isCounterClockwiseForAll(const Point &previous, const Point &candidate, const std::vector<Point> & points) {
-    for (const auto &point : points) {
-        if (previous == point || candidate == point) {
-            continue;
-        }
-        if (orientation(previous, point, candidate) != Counterclockwise) {
-            return false;
-        }
-    }
-    return true;
-}
-*/
 
-/*
-Point nextPoint(const Point &previous, std::vector<Point> &candidates, const std::vector<Point> &points) {
-    Point mostCounterclockwise = candidates[0];
-    for (int i = 1; i < candidates.size(); i++) {
-        if (isCounterClockwiseForAll(previous, candidates[i], points)) {
-            Point p = candidates[i];
-            candidates.erase(i + candidates.begin());
-            return p;
-        }
-    }
-
-    return Point{-69,-69};
-}
-*/
 
 float distanceSquared(const Point &p1, const Point &p2)
 {
diff --git a/src/utilities/triangulation.cpp b/src/utilities/triangulation.cpp
index ea59fa8..bc3ab8c 100644
--- a/src/utilities/triangulation.cpp
+++ b/src/utilities/triangulation.cpp
@@ -4,6 +4,7 @@
 #include <triangle.h>
 #include <optional>
 #include <pointList.h>
+#include <orientation.h>
 
 
 
@@ -17,23 +18,19 @@ bool isAnEar(Triangle triangle, const std::vector<Point> &points) {
     return true;
 }
 
-int mod(int a, int b) {
-    return (a + b) % b;
-}
-
-
 
 std::optional<Triangle> removeEar(int &index, PointList &pointList, const std::vector<Point> &allPoints) {
     PointNode &p = pointList.points[index];
-    const int next = pointList.next(p);
-    const int prev = pointList.prev(p);
+    const int next = p.next();
+    const int prev = p.prev();
+
 
     const PointNode &nextNode = pointList.points[next];
     const PointNode &prevNode = pointList.points[prev];
 
     Triangle candidate = Triangle{p.p, nextNode.p, prevNode.p, 0}; 
 
-    if (isAnEar(candidate, allPoints)) {
+    if (orientation(p.p, nextNode.p, prevNode.p) == Counterclockwise && isAnEar(candidate, allPoints)) {
 
         pointList.remove(index);
         index = next;
@@ -61,8 +58,8 @@ std::vector<Triangle> triangulate(std::vector<Point> points) {
     }
 
     const PointNode curr = polygon.points[i];
-    const int next = polygon.next(curr);
-    const int prev = polygon.prev(curr);
+    const int next = curr.next();
+    const int prev = curr.prev();
     
     Triangle last {curr.p, polygon.points[next].p, polygon.points[prev].p, 0};
     result.push_back(last);
diff --git a/tests/quad_tree_tests.cpp b/tests/quad_tree_tests.cpp
new file mode 100644
index 0000000..91a6db9
--- /dev/null
+++ b/tests/quad_tree_tests.cpp
@@ -0,0 +1,16 @@
+#include <gtest/gtest.h>
+#include <quad_tree.h>
+
+TEST (QuadTreeTest, SingleInsertion) {
+    QuadTree q{Box{0, 10, 0, 10}};
+
+    auto t1 = Triangle(Point{0,0}, Point{5,0},  Point{2,3}, 0);
+
+    auto t2 = Triangle(Point{3,1}, Point{6,1}, Point{4,3}, 0);
+    
+
+    q.addTriangle(std::make_shared<Triangle>(t1));
+    q.addTriangle(std::make_shared<Triangle>(t2));
+
+    EXPECT_TRUE(true);
+}
\ No newline at end of file
-- 
GitLab