diff --git a/CMakeLists.txt b/CMakeLists.txt index 61c608d5922d975d1a97623526554c8b4efe1398..e6d36f7ec0e0506a19f3ad0219abab2cab9b3c71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,6 @@ add_executable( src/debug_utilities/mostly_equal.cpp tests/unit_tests/simple_triangle_tests.cpp tests/unit_tests/point_in_triangle_tests.cpp - tests/unit_tests/triangulation_tests.cpp - tests/unit_tests/ear_removal_tests.cpp src/utilities/intersections.cpp tests/union_tests.cpp src/shapes/triangle.cpp @@ -37,13 +35,10 @@ add_executable( src/utilities/orientation.cpp src/shapes/point.cpp src/union.cpp - src/utilities/triangulation.cpp src/utilities/pointList.cpp tests/unit_tests/orientation_tests.cpp tests/unit_tests/intersections_tests.cpp src/data_structures/box.cpp - src/data_structures/quad_tree.cpp - tests/quad_tree_tests.cpp tests/edge_union_cases.cpp tests/unit_tests/convex_triangulation_tests.cpp src/utilities/convex_triangulation.cpp @@ -53,6 +48,9 @@ add_executable( src/utilities/split_triangle.cpp tests/unit_tests/orientation_tests.cpp tests/union_neighbours_tests.cpp + src/debug_utilities/shift_triangle.cpp + src/utilities/interpolate_z.cpp + tests/unit_tests/interpolate_z_tests.cpp ) include_directories(include) diff --git a/include/contourize.h b/include/contourize.h index cb605f7fc51edc95bbcf6d8de759e0892e6bc471..4292e9846ff6ec20846bdea61a7babbe6e33aa76 100644 --- a/include/contourize.h +++ b/include/contourize.h @@ -1,9 +1,14 @@ #pragma once #include <vector> +#include <string> +#include <exception> struct Triangle; struct Point; +class ContourizeException : public std::exception { + virtual const char *what() const throw(); +}; // creates a contour from a list of points std::vector<Point> contourize(const std::vector<Point> &points); \ No newline at end of file diff --git a/include/convex_triangulation.h b/include/convex_triangulation.h index 21c08ef86b4dc3876a9694ee5fe03d734fbcba74..e38679e92ad7c842349ccb5f44a97e56a77e99ac 100644 --- a/include/convex_triangulation.h +++ b/include/convex_triangulation.h @@ -5,4 +5,4 @@ #include <vector> // Requires a convex shape -std::vector<Triangle> convexTriangulation(const std::vector<Point> &points, int depth, int triangleId); +std::vector<Triangle> convexTriangulation(const std::vector<Point> &points, int triangleId); diff --git a/include/interpolate_z.h b/include/interpolate_z.h new file mode 100644 index 0000000000000000000000000000000000000000..914b76360a112e65484de01c6f8f8b79057f466c --- /dev/null +++ b/include/interpolate_z.h @@ -0,0 +1,5 @@ +#pragma once +#include <vector> +struct Point; + +float interpolateZ(const std::vector<Point> &shape, const Point &p); \ No newline at end of file diff --git a/include/orientation.h b/include/orientation.h index cc80bc60830f0b052307f3ab00ae8136f3a6e35c..dfaae1f11af02014e7ec11eba8fb55e7331f92cb 100644 --- a/include/orientation.h +++ b/include/orientation.h @@ -1,8 +1,10 @@ #pragma once - +struct Triangle; struct Point; enum Orientation { Clockwise, Collinear, Counterclockwise }; -Orientation orientation(const Point &p1, const Point &p2, const Point &p3); \ No newline at end of file +Orientation orientation(const Point &p1, const Point &p2, const Point &p3); + +Orientation orientation(const Triangle &t); \ No newline at end of file diff --git a/include/point.h b/include/point.h index 7b279aa7d3741126e51eb85defcdde4ac8bdf274..8376d863985304ed01983f306da142faa91a9f08 100644 --- a/include/point.h +++ b/include/point.h @@ -4,6 +4,9 @@ struct Point { float x, y, z; bool operator==(const Point &other) const; + Point operator-(const Point &other) const; + Point operator+(const Point &other) const; + Point operator-() const; }; std::ostream &operator<<(std::ostream &os, Point const &p); diff --git a/include/shift_triangle.h b/include/shift_triangle.h new file mode 100644 index 0000000000000000000000000000000000000000..dabd4cc409e0a11206e3f4fba1def6cab4b53b88 --- /dev/null +++ b/include/shift_triangle.h @@ -0,0 +1,4 @@ +#pragma once +struct Triangle; + +void shiftZ(Triangle &t, float z) ; \ No newline at end of file diff --git a/include/triangle.h b/include/triangle.h index 52fd2d8d90ffb0151d659a8a17c4d28f73a5d319..7240edf340d93f395bdfb63f001253ba36e76b2e 100644 --- a/include/triangle.h +++ b/include/triangle.h @@ -3,7 +3,7 @@ #include "print_triangle.h" #include <vector> -// points specified counterclockwise +// points specified in counterclockwise or collinear (line / point) order struct Triangle { Point points[3]; diff --git a/include/triangulation.h b/include/triangulation.h deleted file mode 100644 index 39153ae06589f144c57b1ef775dc6a9500436d81..0000000000000000000000000000000000000000 --- a/include/triangulation.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include <vector> -#include <optional> -#include <triangle.h> - -class PointList; -struct Point; - -std::optional<Triangle> removeEar(int &index, PointList &pointList, const std::vector<Point> &allPoints, int depth, int id); - -std::vector<Triangle> triangulate(std::vector<Point> points, int depth, int id); - -std::vector<Triangle> triangulate(Triangle t1, Triangle t2); \ No newline at end of file diff --git a/src/data_structures/quad_tree.cpp b/src/data_structures/quad_tree.cpp deleted file mode 100644 index c192453efd277444c6dc59769d2687bd9cf8556b..0000000000000000000000000000000000000000 --- a/src/data_structures/quad_tree.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include <quad_tree.h> -#include <union.h> - -QuadTree::QuadTree(Box b) : b{b} {} - -int QuadTree::pointIntersection(Point p) const -{ - int triangleId = POINT_NOT_IN_QUADTREE; - if (!b.isIn(p)) - { - return POINT_NOT_IN_QUADTREE; - } - if (triangles.size() > 0) - { - int depth = INT32_MAX; - for (const Triangle &t : triangles) - { - if (t.depth < depth && t.pointInTriangle(p)) - { - depth = t.depth; - triangleId = t.id; - } - } - return triangleId; - } - - for (const QuadTree &q : children) - { - int id = q.pointIntersection(p); - if (id != POINT_NOT_IN_QUADTREE) - { - triangleId = POINT_NOT_IN_QUADTREE; - } - } - return triangleId; -} - -void QuadTree::addTriangle(Triangle triangle) -{ - - if (!b.isIn(triangle)) - { - return; - } - - if (triangles.size() >= QUADTREE_NODE_MAX_SHAPE && children.empty()) - { - 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})}; - - for (QuadTree &c : children) - { - - c.addTriangle(triangle); - for (const Triangle &t : triangles) - { - c.addTriangle(t); - } - } - triangles.clear(); - return; - } - - if (children.empty()) - { - triangles.push_back(triangle); - return; - } - - for (QuadTree &c : children) - { - for (const Triangle &t : triangles) - { - c.addTriangle(t); - } - } -} \ No newline at end of file diff --git a/src/debug_utilities/mostly_equal.cpp b/src/debug_utilities/mostly_equal.cpp index 63f9d127e55bf7678af92aa54f3134d94cf11267..98585a319ad0223132163c32917357eea6c2f25c 100644 --- a/src/debug_utilities/mostly_equal.cpp +++ b/src/debug_utilities/mostly_equal.cpp @@ -17,6 +17,5 @@ bool Triangle::operator==(const Triangle &other) const { return mostlyEqual(points[0], other.points[0]) && mostlyEqual(points[1], other.points[1]) && mostlyEqual(points[2], other.points[2]) && - depth == other.depth && id == other.id; } \ No newline at end of file diff --git a/src/debug_utilities/print_triangles.cpp b/src/debug_utilities/print_triangles.cpp index 4230de06b4169c1aae7e74d5b9b7b6323ae090dc..679c7f9465eb1f5cf359c4e44a1c04d1f94c278b 100644 --- a/src/debug_utilities/print_triangles.cpp +++ b/src/debug_utilities/print_triangles.cpp @@ -4,7 +4,6 @@ std::ostream &operator<<(std::ostream &os, const Triangle &t) { return os << "Triangle: " << t.id - << ", " << "Depth: " << t.depth << " {" << t.points[0] << ", " << t.points[1] << ", " << t.points[2] << "}"; } /* diff --git a/src/debug_utilities/shift_triangle.cpp b/src/debug_utilities/shift_triangle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f76e8b41c7f994b55cbfd93212f29e1ddd780ea --- /dev/null +++ b/src/debug_utilities/shift_triangle.cpp @@ -0,0 +1,9 @@ +#include <shift_triangle.h> +#include <triangle.h> +#include <constants.h> + +void shiftZ(Triangle &t, float z) { + for (int i =0; i < NB_TRIANGLE_SIDES; i++) { + t.points[i].z += z; + } +} \ No newline at end of file diff --git a/src/shapes/point.cpp b/src/shapes/point.cpp index ce13d15f7deeff30f05890bf93ecc0f58572f501..bd2de6a33344da954d471c4e7089f0e1c087ba6c 100644 --- a/src/shapes/point.cpp +++ b/src/shapes/point.cpp @@ -9,3 +9,17 @@ bool Point::operator==(const Point &other) const { std::ostream &operator<<(std::ostream &os, Point const &p) { return os << "(" << p.x << "," << p.y << "," << p.z << ")"; } + +Point Point::operator-() const { + return {-x, -y,-z}; +} + + +Point Point::operator+(const Point &other) const { + return {x + other.x, y + other.y, z + other.z}; +} + + +Point Point::operator-(const Point &other) const { + return *this + (- other); +} \ No newline at end of file diff --git a/src/shapes/triangle.cpp b/src/shapes/triangle.cpp index 97aff7afbe8ba2091bf14eac6d7d26e16d6c4f3a..53d346d3747a81af8c645045a48d3fdc55371fe1 100644 --- a/src/shapes/triangle.cpp +++ b/src/shapes/triangle.cpp @@ -2,7 +2,7 @@ #include "triangle_edges.h" #include "edge.h" -Triangle::Triangle(const Point &p1, const Point &p2, const Point &p3, int depth, int id, std::vector<int> neighbours) : points{p1,p2,p3}, depth{depth}, id{id}, neighbours{neighbours} {} +Triangle::Triangle(const Point &p1, const Point &p2, const Point &p3, int id, std::vector<int> neighbours) : points{p1,p2,p3}, id{id}, neighbours{neighbours} {} bool Triangle::pointInTriangle(const Point &p) const { // all tests must be positive diff --git a/src/union.cpp b/src/union.cpp index 48d60ba8a40efb0aeff9aad8f967e9721bc6e903..523cf7a2efbc2a7fbd154972b7c31637280bba26 100644 --- a/src/union.cpp +++ b/src/union.cpp @@ -6,13 +6,12 @@ #include <triangle_edges.h> #include <intersections.h> #include <split_triangle.h> -#include <triangulation.h> +#include <convex_triangulation.h> std::vector<Triangle> unionizeTopAndBottom(const Triangle &top, const Triangle &bot) { std::vector<Triangle> result; - std::list<Point> intr; TriangleEdges topEdges = TriangleEdges(top); // keep track of relevant triangles @@ -21,13 +20,16 @@ std::vector<Triangle> unionizeTopAndBottom(const Triangle &top, const Triangle & for (int i = 0; i < NB_TRIANGLE_SIDES; i++) { const Edge &e = topEdges.edges[i]; + + // index 0: On the "outside" of the edge + // index 1: On the "inside" of the edge auto shapes = splitShape(relv, e); // split triangle if exists // currently relevant triangles // add these to result if (!shapes[0].empty()) { - std::vector<Triangle> relvTriangles = triangulate(shapes[0], bot.depth, bot.id); + std::vector<Triangle> relvTriangles = convexTriangulation(shapes[0], bot.id); result.insert(result.end(), relvTriangles.begin(), relvTriangles.end()); } // future relevant triangles @@ -47,7 +49,7 @@ std::vector<Triangle> unionize(const Triangle &t1, const Triangle &t2) { return {t1, t2}; } - if (t1.depth < t2.depth) + if (t1.points[0].z < t2.points[0].z) { return unionizeTopAndBottom(t1, t2); } diff --git a/src/utilities/contourize.cpp b/src/utilities/contourize.cpp index 920b62a2ee3fe295bf277fa8b5f2d0c76928815a..9d5cfc3b27085924849f3b54e5adb49f36592096 100644 --- a/src/utilities/contourize.cpp +++ b/src/utilities/contourize.cpp @@ -3,12 +3,20 @@ #include <orientation.h> #include <list> +const char* ContourizeException::what() const throw() { + return "Infinite Loop detected"; +} + bool isCounterClockwiseForAll(const Point &previous, const Point &candidate, const std::vector<Point> & points) { for (const auto &point : points) { if (previous == point || candidate == point) { continue; } auto o = orientation(previous, candidate, point); + if (o == Collinear) { + continue; + } + if (o != Counterclockwise) { return false; } @@ -21,19 +29,34 @@ std::vector<Point> contourize(const std::vector<Point> &points) { return points; } + + std::vector<Point> result; Point previous = points[0]; result.push_back(previous); std::list<Point> candidates(points.begin() + 1, points.end()); + const int size = candidates.size(); + + // infinite loop detection + int seen = 0; + while (!candidates.empty()) { + // detect infinite loop + if (seen >= candidates.size()) { + throw ContourizeException(); + } + + if (isCounterClockwiseForAll(previous, candidates.front(), points)) { previous = candidates.front(); candidates.pop_front(); - result.push_back(previous); + result.push_back(previous); + seen = 0; } else { candidates.push_back(candidates.front()); candidates.pop_front(); + seen++; } } return result; diff --git a/src/utilities/convex_triangulation.cpp b/src/utilities/convex_triangulation.cpp index c9ba15d41947163b4418f8c9955fa7bc084bfb61..5dd8ca969da7cbe75ec85c2cde12d2f9e2bae99e 100644 --- a/src/utilities/convex_triangulation.cpp +++ b/src/utilities/convex_triangulation.cpp @@ -1,18 +1,18 @@ #include <convex_triangulation.h> -std::vector<Triangle> convexTriangulation(const std::vector<Point> &points, int depth, int triangleId) { +std::vector<Triangle> convexTriangulation(const std::vector<Point> &points, int triangleId) { const int size = points.size(); if (size < 3) { return std::vector<Triangle>{}; } - const Triangle t1 = Triangle(points[0], points[1], points[2], depth, triangleId); + const Triangle t1 = Triangle(points[0], points[1], points[2], triangleId); std::vector<Triangle> results = {t1}; Point first = points[0]; for (int i = size - 1; i >= 3; i--) { - results.push_back(Triangle(first, points[2], points[i], depth, triangleId)); + results.push_back(Triangle(first, points[2], points[i], triangleId)); first = points[i]; } return results; diff --git a/src/utilities/interpolate_z.cpp b/src/utilities/interpolate_z.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b822762bba03688c42a7066b81371d781d26c088 --- /dev/null +++ b/src/utilities/interpolate_z.cpp @@ -0,0 +1,26 @@ +#include <interpolate_z.h> +#include <limits> +#include <point.h> +#include <cmath> + + +float interpolateZ(const std::vector<Point> &shape, const Point &p) { + // create direction vectors + const Point v1 = -(shape[0] - shape[1]); + const Point v2 = -(shape[0] - shape[2]); + + const Point &origin = shape[0]; + + float t = (p.y * v1.x - origin.y * v1.x - p.x * v1.y + origin.x * v1.y) / (v1.x * v2.y - v1.y * v2.x); + float s = (p.y - origin.y - t * v2.y) / v1.y; + + if (s == - std::numeric_limits<float>::infinity() || std::isnan(s)) { + s = 0; + } + + if (t == - std::numeric_limits<float>::infinity() || std::isnan(t)) { + t = 0; + } + + return origin.z + v1.z * s + v2.z * t; +} diff --git a/src/utilities/intersections.cpp b/src/utilities/intersections.cpp index 23551eece5277d679684672e77f93354a20f5c61..660443f5fa74f3d6813c4b203df43a431bbc9844 100644 --- a/src/utilities/intersections.cpp +++ b/src/utilities/intersections.cpp @@ -4,6 +4,7 @@ #include <triangle.h> #include <constants.h> #include <edge.h> +#include <interpolate_z.h> std::optional<float> getB(std::optional<float> slope, Point p) { @@ -138,7 +139,6 @@ std::optional<Point> intersection(const Edge &e1, const Edge &e2) { return {}; } - return candPoint; } void intersections(const Edge &e1, const TriangleEdges &te, std::vector<Point> &results) @@ -172,6 +172,9 @@ std::vector<Point> intersections(const std::vector<Point> &points, const Edge &l auto cand = intersectionFirstSide(line, es[i]); if (cand.has_value()) { + // add depth information + float z = interpolateZ(points, cand.value()); + cand.value().z = z; result.push_back(cand.value()); } } diff --git a/src/utilities/orientation.cpp b/src/utilities/orientation.cpp index fcbfbf990d456ef93a66cd2173c6db9eec2001ee..02bc8f23ad9536aee2afade4a56e5232ce30707e 100644 --- a/src/utilities/orientation.cpp +++ b/src/utilities/orientation.cpp @@ -1,5 +1,6 @@ #include "orientation.h" #include <point.h> +#include <triangle.h> float edgeValue(const Point &p1, const Point &p2) { return (p2.x - p1.x) * (p2.y + p1.y); @@ -12,4 +13,9 @@ Orientation orientation(const Point &p1, const Point &p2, const Point &p3) { } return (val > 0) ? Clockwise : Counterclockwise; +} + + +Orientation orientation(const Triangle &t) { + return orientation(t.points[0], t.points[1], t.points[2]); } \ No newline at end of file diff --git a/src/utilities/triangulation.cpp b/src/utilities/triangulation.cpp deleted file mode 100644 index 539517b418a57d1e22b424cad4acbd08845e95de..0000000000000000000000000000000000000000 --- a/src/utilities/triangulation.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "triangulation.h" -#include <list> -#include <point.h> -#include <triangle.h> -#include <optional> -#include <pointList.h> -#include <orientation.h> - - - - -bool isAnEar(Triangle triangle, const std::vector<Point> &points) { - for (const Point &p: points) { - if (triangle.pointInTriangle(p)) { - return false; - } - } - return true; -} - - -std::optional<Triangle> removeEar(int &index, PointList &pointList, const std::vector<Point> &allPoints,int depth, int id) { - PointNode &p = pointList.points[index]; - 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, depth, id}; - - if (orientation(p.p, nextNode.p, prevNode.p) == Counterclockwise && isAnEar(candidate, allPoints)) { - - pointList.remove(index); - index = next; - - return candidate; - } - index = next; - return {}; - -} - - - -std::vector<Triangle> triangulate(std::vector<Point> points, int depth, int id) { - std::vector<Triangle> result; - - PointList polygon = PointList(points); - int i = 0; - while (polygon.getSize() >= 4) { - - std::optional<Triangle> t = removeEar(i, polygon, points, depth, id); - if (t.has_value()) { - result.push_back(t.value()); - } - } - - const PointNode curr = polygon.points[i]; - const int next = curr.next(); - const int prev = curr.prev(); - - Triangle last {curr.p, polygon.points[next].p, polygon.points[prev].p, depth, id}; - result.push_back(last); - - - return result; - -} \ No newline at end of file diff --git a/tests/edge_union_cases.cpp b/tests/edge_union_cases.cpp index 30bf2e4797fb7610a29f23066029d7f3f9c1954b..c118d48c7608dc3fb8cafd51a9c75cf03f0e3498 100644 --- a/tests/edge_union_cases.cpp +++ b/tests/edge_union_cases.cpp @@ -1,21 +1,77 @@ #include <gtest/gtest.h> #include <union.h> #include <triangle.h> +#include <orientation.h> -TEST(UnionEdgeTests, TriangleVertexOnEdge) { - Triangle t1 = Triangle({}, {}, {}, 1, 1); - Triangle t2 = Triangle({}, {}, {}, 2, 2); +struct UnionParams +{ + Triangle t1; + Triangle t2; + std::vector<Triangle> expected; +}; + +std::ostream &operator<<(std::ostream &os, const UnionParams &u) { + os << u.t1 << "|" << u.t2; + return os; +} + +class InstantiateUnionEdgeTests : public testing::TestWithParam<UnionParams> +{ +}; + +TEST_P(InstantiateUnionEdgeTests, UnionTest) +{ + const Triangle &t1 = GetParam().t1; + const Triangle &t2 = GetParam().t2; + auto expected = GetParam().expected; + + ASSERT_NE(orientation(t1), Clockwise); + ASSERT_NE(orientation(t2), Clockwise); auto result = unionize(t1, t2); + EXPECT_EQ(result, expected); +} + +INSTANTIATE_TEST_SUITE_P(EdgeUnionTests, InstantiateUnionEdgeTests, testing::Values( + // Point on top of triangle + UnionParams{Triangle({0, 0, 4}, {5, 0, 4}, {2, 3, 4}, 1), Triangle({1, 1, 0}, {1, 1, 0}, {1, 1, 0}, 2), {Triangle({0, 0, 4}, {5, 0, 4}, {2, 3, 4}, 1), Triangle({1, 1, 0}, {1, 1, 0}, {1, 1, 0}, 2)}}, + // Point on edge of triangle + UnionParams{Triangle({0, 0, 6}, {5, 0, 6}, {2, 3, 6}, 1), Triangle({0, 2, 3}, {0, 2, 3}, {0, 2, 3}, 2), {Triangle({0, 0, 6}, {5, 0, 6}, {2, 3, 6}, 1), Triangle({0, 2, 3}, {0, 2, 3}, {0, 2, 3}, 2)}}, + // Point on vertex of triangle + UnionParams{Triangle({0, 0, 2}, {5,0,2}, {2,3,2}, 1), Triangle({0,0,0}, {0,0,0}, {0,0,0}, 2), {Triangle({0, 0, 2}, {5,0,2}, {2,3,2}, 1), Triangle({0,0,0}, {0,0,0}, {0,0,0}, 2)}} + )); + +TEST(UnionEdgeTests, TriangleVertexOnEdge) +{ + Triangle t1 = Triangle({}, {}, {}, 1); + Triangle t2 = Triangle({}, {}, {}, 2); + + auto result = unionize(t1, t2); } -TEST(UnionEdgeTests, TriangleEdgeLength0) { - Triangle t1 = Triangle({1,1}, {2,2}, {3,3}, 1, 1); - Triangle t2 = Triangle({}, {}, {}, 2, 2); +TEST(UnionEdgeTests, TriangleIsPoint) +{ + Triangle t1 = Triangle({1, 1, 2}, {2, 2, 2}, {3, 3, 2}, 1); + Triangle t2 = Triangle({2, 2, 1}, {2, 2, 1}, {2, 2, 1}, 2); + + auto results = unionize(t1, t2); + + std::vector<Triangle> expected = { + Triangle({1, 1, 2}, {2, 2, 2}, {3, 3, 2}, 1), + Triangle({2, 2, 1}, {2, 2, 1}, {2, 2, 1}, 2)}; + + EXPECT_EQ(results, expected); } -TEST(UnionEdgeTests, TriangleOnSide) { - Triangle t1 = Triangle({}, {}, {}, 1, 1); - Triangle t2 = Triangle({}, {}, {}, 2, 2); +TEST(UnionEdgeTests, TriangleOnSide) +{ + Triangle t1 = Triangle({0, 0, 1}, {0, 5, 1}, {2, 3, 1}, 1); + Triangle t2 = Triangle({0, 1}, {1, 1}, {0, 3}, 2); + + auto results = unionize(t1, t2); + + std::vector<Triangle> expected; + + EXPECT_EQ(results, expected); } diff --git a/tests/quad_tree_tests.cpp b/tests/quad_tree_tests.cpp deleted file mode 100644 index cbe8689d49ba2bb1ef1ad1958da316e0335d98e0..0000000000000000000000000000000000000000 --- a/tests/quad_tree_tests.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include <gtest/gtest.h> -#include <quad_tree.h> - -/* -TEST (QuadTreeTest, OverlappingTriangles) { - - QuadTree q{Box{0, 10, 0, 10}}; - auto t1 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 1); - auto t2 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 2); - auto t3 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 3); - auto t4 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 4); - auto t5 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 5); - - q.addTriangle(t1); - q.addTriangle(t2); - q.addTriangle(t3); - q.addTriangle(t4); - q.addTriangle(t5); - EXPECT_EQ(q.pointIntersection(Point{1,1}), 1); - -} -*/ -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(t1); - q.addTriangle(t2); - - EXPECT_TRUE(true); -} - -TEST (QuadTreeTest, PointOnTriangleQueryTest) { - QuadTree q{Box{0, 10, 0, 10}}; - - auto t1 = Triangle(Point{0,0}, Point{5,0}, Point{2,3}, 1, 1); - - auto t2 = Triangle(Point{3,1}, Point{6,1}, Point{4,3}, 2, 2); - - - q.addTriangle(t1); - q.addTriangle(t2); - - EXPECT_EQ(q.pointIntersection(Point{1,1}), 1); - EXPECT_EQ(q.pointIntersection(Point{5,1.5}), 2); - EXPECT_EQ(q.pointIntersection(Point{3.5, 1.5}), 1); - EXPECT_EQ(q.pointIntersection(Point{-1,-1}), POINT_NOT_IN_QUADTREE); - -} diff --git a/tests/union_neighbours_tests.cpp b/tests/union_neighbours_tests.cpp index 0896426acafb485fb59d7f8e7c705a1674758721..e595e35579717451bbde9c15e192bfcd32afc26c 100644 --- a/tests/union_neighbours_tests.cpp +++ b/tests/union_neighbours_tests.cpp @@ -3,8 +3,8 @@ #include <union.h> TEST (UnionNeighbourTests, NeighbourTest) { - Triangle t1 = Triangle({}, {}, {}, 1, 1, {2}); - Triangle t2 = Triangle({}, {}, {}, 2, 2, {1}); + Triangle t1 = Triangle({}, {}, {}, 1, {2}); + Triangle t2 = Triangle({}, {}, {}, 2, {1}); auto results = unionize(t1, t2); std::vector<Triangle> expected ={t1, t2} ; diff --git a/tests/union_tests.cpp b/tests/union_tests.cpp index ace3d5bce477a0b2881fc1467bf43a61d9d9debf..900335aa49fbf6a27940db7d9f12c05c5c88ae77 100644 --- a/tests/union_tests.cpp +++ b/tests/union_tests.cpp @@ -2,6 +2,7 @@ #include <union.h> #include <triangle.h> #include <orientation.h> +#include <shift_triangle.h> TEST(UnionTrivialTests, NotTouching) { @@ -16,27 +17,27 @@ TEST(UnionTrivialTests, NotTouching) TEST(UnionTests, TwoIntersections) { - auto t1 = Triangle(Point{0, 0}, Point{5, 0}, Point{2, 3}, 0, 1); - auto t2 = Triangle(Point{3, 1}, Point{6, 1}, Point{4, 3}, 1, 2); + auto t1 = Triangle(Point{0, 0, 0}, Point{5, 0, 0}, Point{2, 3, 0}, 1); + auto t2 = Triangle(Point{3, 1, 1}, Point{6, 1, 1}, Point{4, 3, 1}, 2); auto ts = unionize(t1, t2); EXPECT_TRUE(ts.size() == 3); std::vector<Triangle> expected{ - Triangle({6,1}, {4,3}, {4,1}, 1, 2), - Triangle({4,3}, {3.33333,1.66667}, {4,1}, 1,2), - Triangle({0,0}, {5,0}, {2,3}, 0, 1)}; + Triangle({6,1,1}, {4,3,1}, {3.333333,1.66666,1}, 2), + Triangle({4,3,1}, {3.33333,1.66667,1}, {4,1,1},2), + Triangle({0,0}, {5,0}, {2,3}, 1)}; EXPECT_EQ(ts, expected); } // Edge Case -/* + TEST(UnionTests, SharesPointTest) { // Case 1 t1 covers t2 - Triangle bottom = Triangle({0, 5}, {3, 2}, {5, 3}, 1, 1); - Triangle top = Triangle({0.1, 7}, {5, 3}, {3.2, 9}, 2, 2); + Triangle top = Triangle({0, 5}, {3, 2}, {5, 3}, 1); + Triangle bottom = Triangle({0.1, 7, 5}, {5, 3,5}, {3.2, 9,5}, 2); auto results = unionize(bottom, top); std::vector<Triangle> expected_results_1; @@ -44,41 +45,41 @@ TEST(UnionTests, SharesPointTest) EXPECT_EQ(results, expected_results_1); // Case 2 t2 covers t1 - bottom.depth = 3; + shiftZ(top, 10); results = unionize(bottom, top); std::vector<Triangle> expected_results_2; EXPECT_EQ(results, expected_results_2); -}*/ +} TEST(UnionTests, FoldTriangleTest) { - Triangle top = Triangle({0, 5}, {3, 2}, {5, 3}, 1, 1); - Triangle bottom = Triangle({0.1, 9}, {2, 4}, {5,5}, 2, 2); + Triangle top = Triangle({0, 5}, {3, 2}, {5, 3}, 1); + Triangle bottom = Triangle({0.1, 9,1}, {2, 4,1}, {5,5,1}, 2); auto results = unionize(bottom, top); std::vector<Triangle> expected_results_1 = { - Triangle({0.1, 9}, {1.91038, 4.23585}, {5,5}, 2, 2), - Triangle({1.91038,4.23585}, {2.27273,4.09091}, {5, 5}, 2, 2), - Triangle({0,5}, {3,2}, {5,3}, 1, 1) + Triangle({0.1, 9,1}, {1.91038, 4.23585,1}, {5,5}, 2), + Triangle({1.91038,4.23585,1}, {2.27273,4.09091,1}, {5, 5}, 2), + Triangle({0,5}, {3,2}, {5,3}, 1) }; EXPECT_EQ(results, expected_results_1); - top.depth = 3; + shiftZ(top, 3); results = unionize(bottom, top); std::vector<Triangle> expected_results_2 = { - Triangle({0,5}, {2.6129, 2.3871}, {1.91038, 4.23585}, 3, 1), - Triangle({3,2}, {5, 3}, {2.6129, 2.3871}, 3, 1), - Triangle({5,3}, {2.27273, 4.09091}, {2.6129, 2.3871}, 3, 1), - Triangle({2.27273,4.09091}, {2, 4}, {2.6129, 2.3871}, 3, 1), - Triangle({0.1,9}, {2, 4}, {5, 5}, 2, 2) + Triangle({0,5}, {2.6129, 2.3871}, {1.91038, 4.23585}, 1), + Triangle({3,2}, {5, 3}, {2.6129, 2.3871}, 1), + Triangle({5,3}, {2.27273, 4.09091}, {2.6129, 2.3871}, 1), + Triangle({2.27273,4.09091}, {2, 4}, {2.6129, 2.3871}, 1), + Triangle({0.1,9}, {2, 4}, {5, 5}, 2) }; EXPECT_EQ(results, expected_results_2); @@ -106,8 +107,8 @@ TEST(UnionTests, IceCreamTest) TEST(UnionTests, StarTest) { - Triangle bottom = Triangle({0, 3}, {5, 3}, {2.5, 6}, 1, 1); - Triangle top = Triangle({0, 5}, {2, 0}, {5, 5}, 2, 2); + Triangle bottom = Triangle({0, 3}, {5, 3}, {2.5, 6}, 1); + Triangle top = Triangle({0, 5, 1}, {2, 0, 1}, {5, 5, 1}, 2); ASSERT_EQ(orientation(bottom.points[0], bottom.points[1], bottom.points[2]), Counterclockwise); ASSERT_EQ(orientation(top.points[0], top.points[1], top.points[2]), Counterclockwise); @@ -115,24 +116,28 @@ TEST(UnionTests, StarTest) auto results = unionize(bottom, top); std::vector<Triangle> expected_results_1 = { - Triangle({2,0}, {3.8, 3}, {0.8, 3}, 2, 2), - Triangle({5,5}, {3.33333, 5}, {4.30233, 3.83721}, 2, 2), - Triangle({0,5}, {0.540541, 3.64865}, {1.66667, 5}, 2, 2), - Triangle({0, 3}, {5, 3}, {2.5, 6}, 1, 1) + Triangle({2,0}, {3.8, 3}, {0.8, 3}, 2), + Triangle({5,5}, {3.33333, 5}, {4.30233, 3.83721}, 2), + Triangle({0,5}, {0.540541, 3.64865}, {1.66667, 5}, 2), + Triangle({0, 3}, {5, 3}, {2.5, 6}, 1) }; EXPECT_EQ(results, expected_results_1); - bottom.depth = 3; + shiftZ(bottom, 3); results = unionize(bottom, top); std::vector<Triangle> expected_results_2 = { - Triangle({0,3}, {0.8,3}, {0.540541,3.64865}, 3, 1), - Triangle({5,3}, {4.30233,3.83721}, {3.8,3}, 3, 1), - Triangle({2.5,6}, {1.66667,5}, {3.33333,5}, 3, 1), - Triangle({0,5}, {2,0}, {5,5}, 2, 2) + Triangle({0,3}, {0.8,3}, {0.540541,3.64865}, 1), + Triangle({5,3}, {4.30233,3.83721}, {3.8,3}, 1), + Triangle({2.5,6}, {1.66667,5}, {3.33333,5}, 1), + Triangle({0,5}, {2,0}, {5,5}, 2) }; EXPECT_EQ(results, expected_results_2); } + +TEST (UnionTests, DepthTest) { + +} \ No newline at end of file diff --git a/tests/unit_tests/contourize_tests.cpp b/tests/unit_tests/contourize_tests.cpp index c4c9d10b7a2052a40edaacb996be0b8851c4d74d..80f0f6a3451a4d1fbf8f93f2c931dd3ebedb0930 100644 --- a/tests/unit_tests/contourize_tests.cpp +++ b/tests/unit_tests/contourize_tests.cpp @@ -4,11 +4,11 @@ #include <intersections.h> TEST(ContourizeTest, Simple) { - std::vector<Point> points{{6,1}, {4,3}, {4, 1}, {3.3333, 1.6666}}; + std::vector<Point> points{{0,0}, {0,5}, {2, 3}}; auto result = contourize(points); - std::vector<Point> expected{{4,1}, {3.3333,1.6666}, {4,3}, {6,1}}; + std::vector<Point> expected{{0,0}, {0,5}, {2, 3}}; EXPECT_EQ(result, expected); } diff --git a/tests/unit_tests/convex_triangulation_tests.cpp b/tests/unit_tests/convex_triangulation_tests.cpp index 21c77eb55fb784707ce63a65565e58855ed19223..5fa45e1408ca2fc77b8998f2c95c142c12d639c2 100644 --- a/tests/unit_tests/convex_triangulation_tests.cpp +++ b/tests/unit_tests/convex_triangulation_tests.cpp @@ -14,12 +14,12 @@ TEST(ConvexTriangulationTests, Simple) { p1, p2, p3, p4, p5 }; - auto results = convexTriangulation(points, 2, 2); + auto results = convexTriangulation(points, 2); std::vector<Triangle> expected_result { - Triangle(p1, p2, p3, 2, 2), - Triangle(p1, p3, p5, 2, 2), - Triangle(p5, p3, p4, 2, 2) + Triangle(p1, p2, p3, 2), + Triangle(p1, p3, p5, 2), + Triangle(p5, p3, p4, 2) }; EXPECT_EQ(results, expected_result); @@ -33,8 +33,8 @@ TEST(ConvexTriangulationTests, TrivialTriangle) { {1.5, 2} }; - auto results = convexTriangulation(points, 1, 1); - Triangle expected_triangle = Triangle({0,0}, {2,0}, {1.5, 2}, 1, 1); + auto results = convexTriangulation(points, 1); + Triangle expected_triangle = Triangle({0,0}, {2,0}, {1.5, 2}, 1); EXPECT_EQ(results.size(), 1); EXPECT_EQ(results[0], expected_triangle); diff --git a/tests/unit_tests/ear_removal_tests.cpp b/tests/unit_tests/ear_removal_tests.cpp deleted file mode 100644 index ed567b806805a0873de178ce6ebb4ffd986dddcf..0000000000000000000000000000000000000000 --- a/tests/unit_tests/ear_removal_tests.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include <gtest/gtest.h> -#include <triangulation.h> -#include <vector> -#include <point.h> -#include <pointList.h> - -TEST(EarRemovalTests, SingleEarRemoval) { - std::vector<Point> polygon = { - {3,48}, {52, 8}, {99,50}, {138,25}, - {175, 77}, {131, 72}, {111, 113}, - {72, 43}, {26, 55}, {29, 100}}; - - PointList pointList = PointList(polygon); - int index = 0; - auto t = removeEar(index, pointList, polygon, 0,0); - EXPECT_FALSE(t.has_value()); - EXPECT_TRUE(true); - - auto t2 = removeEar(index, pointList, polygon,0,0); - - auto t3 = removeEar(index, pointList, polygon,0,0); -} \ No newline at end of file diff --git a/tests/unit_tests/interpolate_z_tests.cpp b/tests/unit_tests/interpolate_z_tests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1fe2aab53d2ada07b4a156c3190cf21bfd4570d --- /dev/null +++ b/tests/unit_tests/interpolate_z_tests.cpp @@ -0,0 +1,26 @@ +#include <gtest/gtest.h> +#include <interpolate_z.h> +#include <point.h> + +struct InterpolateParams { + std::vector<Point> points; + float expected_z; +}; + +class InstantiateInterpolateZTests : public testing::TestWithParam<InterpolateParams>{ +}; + +TEST_P (InstantiateInterpolateZTests, Interpolate) { + + std::vector<Point> points = GetParam().points; + + float z = interpolateZ(points, {0,1,0}); + + EXPECT_EQ(z,GetParam().expected_z); +} + +INSTANTIATE_TEST_SUITE_P(Interpolation, InstantiateInterpolateZTests, testing::Values( + InterpolateParams{ + {{1,1,3}, {2,2,3}, {4,5,3}} + , 3}, + InterpolateParams{{{1,1,5}, {1,1,5}, {1,1,5}}, 5})); \ No newline at end of file diff --git a/tests/unit_tests/orientation_tests.cpp b/tests/unit_tests/orientation_tests.cpp index 8f91929dd9ff534138b152e193780950248cdab7..ec9d68d47baa7d7309cfc1801c6c17b5f8c10a90 100644 --- a/tests/unit_tests/orientation_tests.cpp +++ b/tests/unit_tests/orientation_tests.cpp @@ -12,6 +12,10 @@ TEST(OrientationTests, ExampleCounterClockwiseTest) EXPECT_EQ(orientation(Point{0, 0}, Point{4, 4}, Point{1, 2}), Counterclockwise); } +TEST (OrientationTests, Counterclockwise) { + EXPECT_EQ(orientation({0,0}, {5,0}, {2,3}), Counterclockwise); +} + TEST(OrientationTests, TestAll) { Point p1 = {3, 1}; diff --git a/tests/unit_tests/split_triangle_tests.cpp b/tests/unit_tests/split_triangle_tests.cpp index 8185284beb5429381b7f2cf6583a80cbec1f1648..65c1eb373bb9bbfc2af8d95f082bc994245374f1 100644 --- a/tests/unit_tests/split_triangle_tests.cpp +++ b/tests/unit_tests/split_triangle_tests.cpp @@ -4,7 +4,7 @@ #include <edge.h> TEST(SplitTriangleTests, NormalCase) { - Triangle t = Triangle({0,0}, {5,0}, {2,3}, 1, 1); + Triangle t = Triangle({0,0}, {5,0}, {2,3}, 1); Edge e{{4,3}, {3,1}}; auto results = splitShape(std::vector<Point>{t.points[0], t.points[1], t.points[2]}, e); @@ -46,4 +46,24 @@ TEST (SplitTriangleTests, Quadric) { auto results = splitShape(p,e); EXPECT_TRUE(results[0].size() > 2); +} + +TEST(SplitTriangleTests, OnEdge1) { + std::vector<Point> t {{0,0}, {0,5}, {2,3}}; + Edge e = Edge{{1,1}, {0,1}}; + + auto results = splitShape(t, e); + + EXPECT_EQ(results[0].size(), 4); + EXPECT_EQ(results[1].size(), 3); +} + +TEST(SplitTriangleTests, OnEdge2) { + + std::vector<Point> t {{0,0}, {0,5}, {2,3}}; + Edge e {{1,1}, {0,3}}; + + auto results = splitShape(t,e); + + EXPECT_EQ(results[0].size(), 4); } \ No newline at end of file diff --git a/tests/unit_tests/triangulation_tests.cpp b/tests/unit_tests/triangulation_tests.cpp deleted file mode 100644 index 65493fb912f756777ea950fe8e0e4d82795c0211..0000000000000000000000000000000000000000 --- a/tests/unit_tests/triangulation_tests.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "gtest/gtest.h" -#include <point.h> -#include <triangulation.h> - -TEST(TriangulationTests, Page3Example) { - std::vector<Point> polygon = { - {3,48}, {52, 8}, {99,50}, {138,25}, - {175, 77}, {131, 72}, {111, 113}, - {72, 43}, {26, 55}, {29, 100}}; - - auto t = triangulate(polygon, 0, 0); - EXPECT_TRUE(t.size() > 0); -} \ No newline at end of file