From a48c39902fb41dbb00fdcfc172737cae982ebe37 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 16:40:54 +1200 Subject: [PATCH 01/15] Added polygon --- TEST_Geometry2D.cpp | 31 +- olcUTIL_Geometry2D.h | 694 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 717 insertions(+), 8 deletions(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index fbdb6ee..97c80ed 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -86,6 +86,12 @@ class Test_Geometry2D : public olc::PixelGameEngine olc::vf2d points[2]; // origin, direction }; + struct Polygon + { + std::vector points; + Polygon(std::initializer_list list) : points(list) {} + }; + // Create desired shapes using a sequence of points static auto make_internal(const Point& p) { return p.points[0]; } static auto make_internal(const Line& p) { return line{ p.points[0], p.points[1] }; } @@ -93,9 +99,10 @@ class Test_Geometry2D : public olc::PixelGameEngine static auto make_internal(const Circle& p) { return circle{ p.points[0], (p.points[1]-p.points[0]).mag() }; } static auto make_internal(const Triangle& p) { return triangle{ p.points[0], p.points[1], p.points[2] }; } static auto make_internal(const Ray& p) { return ray{ p.points[0], (p.points[1]-p.points[0]).norm() }; } + static auto make_internal(const Polygon& p) { return olc::utils::geom2d::createPolygon(p.points); } // The clever bit (and a bit new to me - jx9) - using ShapeWrap = std::variant; + using ShapeWrap = std::variant; @@ -104,10 +111,10 @@ class Test_Geometry2D : public olc::PixelGameEngine const auto dispatch = overloads{ [](const auto& lhs, const auto& rhs) { - return overlaps(make_internal(lhs), make_internal(rhs)); + return overlaps(make_internal(lhs), make_internal(rhs)); }, - // Any combination of 'Ray' does not work because 'overlaps' is not implemented for it. + // any combination of 'ray' does not work because 'overlaps' is not implemented for it. [](const Ray&, const auto&) { return false; }, [](const auto&, const Ray&) { return false; }, [](const Ray&, const Ray&) { return false; } @@ -216,6 +223,22 @@ class Test_Geometry2D : public olc::PixelGameEngine DrawLine(t.origin, t.origin+t.direction * 1000.0f, col, 0xF0F0F0F0); } + void draw_internal(const Polygon& p, const olc::Pixel col) + { + const auto t = make_internal(p); + for (size_t i = 0; i < t.pos.size(); i++) + { + if (i == t.pos.size() - 1) + { + DrawLine(t.pos[i], t.pos[0], col); + } + else + { + DrawLine(t.pos[i], t.pos[i + 1], col); + } + } + } + void DrawShape(const ShapeWrap& shape, const olc::Pixel col = olc::WHITE) { std::visit([&](const auto& x) @@ -245,6 +268,7 @@ class Test_Geometry2D : public olc::PixelGameEngine vecShapes.push_back({ Triangle{{ {50.0f, 100.0f}, {10.0f, 150.0f}, {90.0f, 150.0f}} }}); vecShapes.push_back({ Triangle{{ {350.0f, 200.0f}, {500.0f, 150.0f}, {450.0f, 400.0f}} }}); + vecShapes.push_back({ Polygon{{ {60.0f, 420.0f}, {10.0f, 370.0f}, {160.0f, 320.0f}, {210.f, 420.0f}, {160.0f, 470.0f}, {10.0f, 470.0f} }} }); return true; } @@ -262,7 +286,6 @@ class Test_Geometry2D : public olc::PixelGameEngine // Check for mouse hovered shapes ShapeWrap mouse{ Point{olc::vf2d(GetMousePos())} }; - if (nSelectedShapeIndex < vecShapes.size() && GetMouse(0).bHeld) { // Visit the selected shape and offset. diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index 641e375..5fdd16e 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -790,6 +790,9 @@ namespace olc::utils::geom2d struct polygon { std::vector> pos; + + // triangles that make up the polygon + std::vector> triangles; }; @@ -896,6 +899,15 @@ namespace olc::utils::geom2d return p; } + // closest(p,p) + // Returns closest point on polygon to point + template + inline olc::v_2d closest(const polygon& p, const olc::v_2d& point) + { + // TODO: + return {}; + } + // Closest location on [SHAPE] to Line @@ -935,6 +947,15 @@ namespace olc::utils::geom2d return {}; } + // closest(p,l) + // Returns closest point on polygon to line + template + inline olc::v_2d closest(const polygon& p, const line& l) + { + // TODO: + return {}; + } + // Closest location on [SHAPE] to Circle @@ -973,6 +994,15 @@ namespace olc::utils::geom2d return {}; } + // closest(p,c) + // Returns closest point on polygon to circle + template + inline olc::v_2d closest(const polygon& p, const circle& c) + { + // TODO: + return {}; + } + // Closest location on [SHAPE] to Triangle @@ -988,7 +1018,7 @@ namespace olc::utils::geom2d // closest(r,t) // Returns closest point on rectangle to triangle template - inline olc::v_2d closest(const rect& r, const triangle& l) + inline olc::v_2d closest(const rect& r, const triangle& t) { // TODO: return {}; @@ -997,7 +1027,7 @@ namespace olc::utils::geom2d // closest(c,t) // Returns closest point on circle to triangle template - inline olc::v_2d closest(const circle& c, const triangle& l) + inline olc::v_2d closest(const circle& c, const triangle& t) { // TODO: return {}; @@ -1006,13 +1036,67 @@ namespace olc::utils::geom2d // closest(t,t) // Returns closest point on triangle to triangle template - inline olc::v_2d closest(const triangle& r, const triangle& l) + inline olc::v_2d closest(const triangle& r, const triangle& t) { // TODO: return {}; } - + // closest(p,t) + // Returns closest point on polygon to triangle + template + inline olc::v_2d closest(const polygon& p, const triangle& t) + { + // TODO: + return {}; + } + + // Closest location on [SHAPE] to Polygon + + // closest(l,p) + // Returns closest point on line to polygon + template + inline olc::v_2d closest(const line& l, const polygon& p) + { + // TODO: + return {}; + } + + // closest(r,p) + // Returns closest point on rectangle to polygon + template + inline olc::v_2d closest(const rect& r, const polygon& p) + { + // TODO: + return {}; + } + + // closest(c,p) + // Returns closest point on circle to polygon + template + inline olc::v_2d closest(const circle& c, const polygon& p) + { + // TODO: + return {}; + } + + // closest(p,p) + // Returns closest point on triangle to polygon + template + inline olc::v_2d closest(const triangle& r, const polygon& p) + { + // TODO: + return {}; + } + + // closest(p,p) + // Returns closest point on polygon to polygon + template + inline olc::v_2d closest(const polygon& r, const polygon& p) + { + // TODO: + return {}; + } @@ -1100,6 +1184,22 @@ namespace olc::utils::geom2d return distance < epsilon; } + // contains(t,p) + // Checks if triangle contains a point + template + inline constexpr bool contains(const polygon& p, const olc::v_2d& point) + { + for (auto& triangle : p.triangles) + { + if (contains(triangle, point) == true) + { + return true; + } + } + + return false; + } + // overlaps(p,p) // Check if point overlaps with point (analogous to contains()) template @@ -1140,6 +1240,14 @@ namespace olc::utils::geom2d return contains(t, p); } + // overlaps(t,p) + // Checks if polygon overlaps with point + template + inline constexpr bool overlaps(const polygon& p, const olc::v_2d& point) + { + return contains(p, point); + } + @@ -1201,6 +1309,19 @@ namespace olc::utils::geom2d } + // intersects(t,p) + // Get intersection points where polygon intersects with point + template + inline std::vector> intersects(const polygon& p, const olc::v_2d& point) + { + for(auto& t : p.triangles) + if (contains(t, p)) + return { point }; + + return {}; + + } + @@ -1255,6 +1376,14 @@ namespace olc::utils::geom2d return contains(t, l.start) && contains(t, l.end); } + // contains(p,l) + // Check if polygon contains line segment + template + inline constexpr bool contains(const polygon& p, const line& l) + { + return contains(p, l.start) && contains(p, l.end); + } + // overlaps(p,l) @@ -1305,6 +1434,22 @@ namespace olc::utils::geom2d return overlaps(t, l.start) || overlaps(t.side(0), l) || overlaps(t.side(1), l) || overlaps(t.side(2), l); } + // overlaps(p,l) + // Check if polygon overlaps line segment + template + inline constexpr bool overlaps(const polygon& p, const line& l) + { + for (auto& triangle : p.triangles) + { + if (overlaps(triangle, l) == true) + { + return true; + } + } + + return false; + } + // intersects(p,l) @@ -1413,6 +1558,22 @@ namespace olc::utils::geom2d return internal::filter_duplicate_points(intersections); } + // intersects(p,l) + // Get intersection points where polygon intersects with line segment + template + inline std::vector> intersects(const polygon& p, const line& l) + { + std::vector> intersections; + + for (auto& triangle : p.triangles) + { + auto v = intersects(triangle, l); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + @@ -1474,6 +1635,17 @@ namespace olc::utils::geom2d && contains(t, olc::v_2d{ r.pos.x, r.pos.y + r.size.y }); } + // contains(p,r) + // Check if polygon contains rect + template + inline constexpr bool contains(const polygon& p, const rect& r) + { + return contains(p, r.pos) + && contains(p, r.pos + r.size) + && contains(p, olc::v_2d{ r.pos.x + r.size.x, r.pos.y }) + && contains(p, olc::v_2d{ r.pos.x, r.pos.y + r.size.y }); + } + // overlaps(p,r) @@ -1526,6 +1698,22 @@ namespace olc::utils::geom2d || contains(r, t.pos[0]); } + // overlaps(p,r) + // Check if polygon overlaps rectangle + template + inline constexpr bool overlaps(const polygon& p, const rect& r) + { + for (auto& triangle : p.triangles) + { + if (overlaps(triangle, r) == true) + { + return true; + } + } + + return false; + } + // intersects(p,r) @@ -1590,7 +1778,21 @@ namespace olc::utils::geom2d return internal::filter_duplicate_points(intersections); } + // intersects(p,r) + // Get intersection points where polygon intersects with rectangle + template + inline std::vector> intersects(const polygon& p, const rect& r) + { + std::vector> intersections; + + for (auto& triangle : p.triangles) + { + auto v = intersects(triangle, r); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + return internal::filter_duplicate_points(intersections); + } @@ -1650,6 +1852,14 @@ namespace olc::utils::geom2d } + // contains(p,l) + // Check if polygon contains circle + template + inline constexpr bool contains(const polygon& p, const circle& c) + { + return false; + } + // overlaps(p,c) // Check if point overlaps circle @@ -1691,6 +1901,22 @@ namespace olc::utils::geom2d return contains(t, c.pos) || (c.pos - closest(t, c.pos)).mag2() <= c.radius * c.radius; } + // overlaps(p,c) + // Check if triangle overlaps circle + template + inline constexpr bool overlaps(const polygon& p, const circle& c) + { + for (auto& triangle : p.triangles) + { + if (overlaps(triangle, c) == true) + { + return true; + } + } + + return false; + } + // intersects(p,c) @@ -1778,6 +2004,22 @@ namespace olc::utils::geom2d + // intersects(p,c) + // Get intersection points where polygon intersects with circle + template + inline std::vector> intersects(const polygon& p, const circle& c) + { + std::vector> intersections; + + for (auto& triangle : p.triangles) + { + auto v = intersects(triangle, c); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + @@ -1837,6 +2079,16 @@ namespace olc::utils::geom2d && contains(t1, t2.pos[2]); } + // contains(p,t) + // Check if polygon contains triangle + template + inline constexpr bool contains(const polygon& p, const triangle& t2) + { + return contains(p, t2.pos[0]) + && contains(p, t2.pos[1]) + && contains(p, t2.pos[2]); + } + // overlaps(p,t) @@ -1882,6 +2134,22 @@ namespace olc::utils::geom2d || overlaps(t2, t1.pos[0]); } + // overlaps(p,t) + // Check if polygon overlaps triangle + template + inline constexpr bool overlaps(const polygon& p, const triangle& t) + { + for (auto& triangle : p.triangles) + { + if (overlaps(triangle, t) == true) + { + return true; + } + } + + return false; + } + // intersects(p,t) @@ -1932,6 +2200,24 @@ namespace olc::utils::geom2d } + + // intersects(p,t) + // Get intersection points where polygon intersects with triangle + template + inline std::vector> intersects(const polygon& p, const triangle& t) + { + std::vector> intersections; + + for (auto& triangle : p.triangles) + { + auto v = intersects(triangle, t); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // envelope_c(c) // Return circle that fully encapsulates a point template @@ -2501,6 +2787,406 @@ namespace olc::utils::geom2d return internal::filter_duplicate_points(intersections); } + + // ================================================================================================================ + // POLYGON ========================================================================================================= + template + inline polygon createPolygon(std::vector> points) + { + polygon returnPolygon; + + std::vector indexList; + + for (size_t i = 0; i < points.size(); i++) + { + indexList.push_back(i); + returnPolygon.pos.push_back(points[i]); + } + + while (indexList.size() > 3) + { + for (size_t i = 0; i < indexList.size(); i++) + { + size_t a = indexList[i]; + size_t b = indexList[i == 0 ? indexList.size() - 1 : i - 1]; + size_t c = indexList[i == indexList.size() - 1 ? 0 : i + 1]; + + triangle thisTriangle; + thisTriangle.pos[0] = points[a]; + thisTriangle.pos[1] = points[b]; + thisTriangle.pos[2] = points[c]; + + olc::v_2d pb_pa = points[b] - points[a]; + olc::v_2d pc_pa = points[c] - points[a]; + float cross = pb_pa.cross(pc_pa); + if (pb_pa.cross(pc_pa) > 0.0f) + { + continue; + } + + bool isEar = true; + + for (size_t j = 0; j < points.size(); j++) + { + if (j == a || j == b || j == c) + { + continue; + } + + if (contains(thisTriangle, points[j]) == true) + { + isEar = false; + break; + } + } + + if (isEar == true) + { + returnPolygon.triangles.push_back(thisTriangle); + + indexList.erase(indexList.begin() + i); + break; + } + } + } + + triangle lastTriangle; + lastTriangle.pos[0] = points[indexList[0]]; + lastTriangle.pos[1] = points[indexList[1]]; + lastTriangle.pos[2] = points[indexList[2]]; + + returnPolygon.triangles.push_back(lastTriangle); + + return returnPolygon; + } + + // overlaps(p,p) + // Check if point overlaps with polygon (analogous to contains()) + template + inline constexpr bool overlaps(const olc::v_2d& p1, const polygon& p2) + { + return contains(p1, p2); + } + + // overlaps(l,p) + // Checks if line segment overlaps with polygon + template + inline constexpr bool overlaps(const line& l, const polygon& p) + { + return contains(l, p); + } + + // overlaps(r,p) + // Checks if rectangle overlaps with polygon + template + inline constexpr bool overlaps(const rect& r, const polygon& p) + { + return contains(r, p); + } + + // overlaps(c,p) + // Checks if circle overlaps with polygon + template + inline constexpr bool overlaps(const circle& c, const polygon& p) + { + return contains(c, p); + } + + // overlaps(t,p) + // Checks if triangle overlaps with polygon + template + inline constexpr bool overlaps(const triangle& t, const polygon& p) + { + return contains(t, p); + } + + // overlaps(t,p) + // Checks if polygon overlaps with polygon + template + inline constexpr bool overlaps(const polygon& p1, const polygon& p2) + { + for (auto& triangle : p1.triangles) + { + if (contains(triangle, p2) == true) + { + return true; + } + } + + return false; + } + + // contains(p,p) + // Check if point contains polygon (analogous to contains()) + template + inline constexpr bool contains(const olc::v_2d& p1, const polygon& p2) + { + for (auto& triangle : p2.triangles) + { + if (contains(triangle, p1) == true) + { + return true; + } + } + + return false; + } + + // contains(l,p) + // Checks if line segment contains polygon + template + inline constexpr bool contains(const line& l, const polygon& p) + { + for (auto& triangle : p.triangles) + { + if (contains(triangle, l) == true) + { + return true; + } + } + + return false; + } + + // contains(r,p) + // Checks if rectangle contains polygon + template + inline constexpr bool contains(const rect& r, const polygon& p) + { + for (auto& triangle : p.triangles) + { + if (contains(triangle, r) == true) + { + return true; + } + } + + return false; + } + + // contains(c,p) + // Checks if circle contains polygon + template + inline constexpr bool contains(const circle& c, const polygon& p) + { + for (auto& triangle : p.triangles) + { + if (contains(triangle, c) == true) + { + return true; + } + } + + return false; + } + + // contains(t,p) + // Checks if triangle contains polygon + template + inline constexpr bool contains(const triangle& t, const polygon& p) + { + for (auto& triangle : p.triangles) + { + if (contains(triangle, t) == true) + { + return true; + } + } + + return false; + } + + // contains(t,p) + // Checks if polygon contains polygon + template + inline constexpr bool contains(const polygon& p1, const polygon& p2) + { + return false; + } + + // intersects(p,p) + // Get intersection points where a point intersects a polygon + template + inline std::vector> intersects(const olc::v_2d& p1, const polygon& p2) + { + std::vector> intersections; + + for (auto& triangle : p2.triangles) + { + auto v = intersects(triangle, p1); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // intersects(l,p) + // Get intersection points where a line intersects a polygon + template + inline std::vector> intersects(const line l, const polygon& p) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(l2, l); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // intersects(r,p) + // Get intersection points where a rectangle intersects a rectangle + template + inline std::vector> intersects(const rect r, const polygon& p) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(l2, r); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // intersects(c,p) + // Get intersection points where a circle intersects a rectangle + template + inline std::vector> intersects(const circle c, const polygon& p) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(l2, c); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // intersects(t,p) + // Get intersection points where a triangle intersects a polygon + template + inline std::vector> intersects(const triangle t, const polygon& p) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(l2, t); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + // intersects(p,p) + // Get intersection points where a polygon intersects a polygon + template + inline std::vector> intersects(const polygon p1, const polygon& p2) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p2.pos.size(); i++) + { + if (i == p2.pos.size() - 1) + { + l2 = { p2.pos[i], p2.pos[0] }; + } + else + { + l2 = { p2.pos[i], p2.pos[i + 1] }; + } + + auto v = intersects(l2, p1); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + + + // intersects(r,p) + // Get intersection points where a ray intersects a polygon + template + inline std::vector> intersects(const ray& r, const polygon& p) + { + line l2; + std::vector> intersections; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(r, l2); + intersections.insert(intersections.end(), v.begin(), v.end()); + } + + return internal::filter_duplicate_points(intersections); + } + + + + // reflect(q,c) + // optionally returns a ray reflected off a circle if collision occurs + template + inline std::optional> reflect(const ray& q, const polygon& c) + { + return std::nullopt; + } } #endif // PGE_VER From e99dd12c1cc041925cf12f50ff964da85af03eaa Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 19:06:11 +1200 Subject: [PATCH 02/15] Fixed intersect functions --- olcUTIL_Geometry2D.h | 56 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index 5fdd16e..deb16a4 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -1563,11 +1563,21 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const line& l) { + line l2; std::vector> intersections; - for (auto& triangle : p.triangles) + for (size_t i = 0; i < p.pos.size(); i++) { - auto v = intersects(triangle, l); + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(l, l2); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -1783,11 +1793,21 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const rect& r) { + line l2; std::vector> intersections; - for (auto& triangle : p.triangles) + for (size_t i = 0; i < p.pos.size(); i++) { - auto v = intersects(triangle, r); + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(r, l2); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -2009,11 +2029,21 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const circle& c) { + line l2; std::vector> intersections; - for (auto& triangle : p.triangles) + for (size_t i = 0; i < p.pos.size(); i++) { - auto v = intersects(triangle, c); + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(c, l2); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -2206,11 +2236,21 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const triangle& t) { + line l2; std::vector> intersections; - for (auto& triangle : p.triangles) + for (size_t i = 0; i < p.pos.size(); i++) { - auto v = intersects(triangle, t); + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = intersects(t, l2); intersections.insert(intersections.end(), v.begin(), v.end()); } From 95832c8a3260d1d834c087325b3d6ce5ecf672a8 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 20:12:50 +1200 Subject: [PATCH 03/15] Fixed reflect function --- TEST_Geometry2D.cpp | 14 +------------- olcUTIL_Geometry2D.h | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index 97c80ed..b17c025 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -255,19 +255,7 @@ class Test_Geometry2D : public olc::PixelGameEngine public: bool OnUserCreate() override { - vecShapes.push_back({ Point{ { { 250.0f, 10.0f } } } }); - - vecShapes.push_back({ Line{ { { 20.0f, 10.0f }, {50.0f, 70.0f} } } }); - vecShapes.push_back({ Line{ { { 80.0f, 10.0f }, {10.0f, 20.0f} } } }); - - vecShapes.push_back({ Rect{ { { 80.0f, 10.0f }, {110.0f, 60.0f} } } }); - - vecShapes.push_back({ Circle{ { { 130.0f, 20.0f }, {170.0f, 20.0f} } } }); - vecShapes.push_back({ Circle{ { { 330.0f, 300.0f }, {420.0f, 300.0f} } } }); - vecShapes.push_back({ Circle{ { { 330.0f, 300.0f }, {400.0f, 300.0f} } } }); - - vecShapes.push_back({ Triangle{{ {50.0f, 100.0f}, {10.0f, 150.0f}, {90.0f, 150.0f}} }}); - vecShapes.push_back({ Triangle{{ {350.0f, 200.0f}, {500.0f, 150.0f}, {450.0f, 400.0f}} }}); + zzz vecShapes.push_back({ Polygon{{ {60.0f, 420.0f}, {10.0f, 370.0f}, {160.0f, 320.0f}, {210.f, 420.0f}, {160.0f, 470.0f}, {10.0f, 470.0f} }} }); return true; diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index deb16a4..efc85a4 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -3220,12 +3220,36 @@ namespace olc::utils::geom2d - // reflect(q,c) + // reflect(r,p) // optionally returns a ray reflected off a circle if collision occurs template - inline std::optional> reflect(const ray& q, const polygon& c) + inline std::optional> reflect(const ray& r, const polygon& p) { - return std::nullopt; + line l2; + T1 length = std::numeric_limits().max(); + std::optional> returnValue = std::nullopt; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + auto v = reflect(r, l2); + + if (v.has_value() && (v.value().origin - r.origin).mag() < length) + { + length = (v.value().origin - r.origin).mag(); + returnValue = v; + } + } + + return returnValue; } } From 5ce7701eeb4d55ecd9b16145a6ec8ab0020b0cc9 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 20:13:49 +1200 Subject: [PATCH 04/15] Fixed test build error --- TEST_Geometry2D.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index b17c025..97c80ed 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -255,7 +255,19 @@ class Test_Geometry2D : public olc::PixelGameEngine public: bool OnUserCreate() override { - zzz + vecShapes.push_back({ Point{ { { 250.0f, 10.0f } } } }); + + vecShapes.push_back({ Line{ { { 20.0f, 10.0f }, {50.0f, 70.0f} } } }); + vecShapes.push_back({ Line{ { { 80.0f, 10.0f }, {10.0f, 20.0f} } } }); + + vecShapes.push_back({ Rect{ { { 80.0f, 10.0f }, {110.0f, 60.0f} } } }); + + vecShapes.push_back({ Circle{ { { 130.0f, 20.0f }, {170.0f, 20.0f} } } }); + vecShapes.push_back({ Circle{ { { 330.0f, 300.0f }, {420.0f, 300.0f} } } }); + vecShapes.push_back({ Circle{ { { 330.0f, 300.0f }, {400.0f, 300.0f} } } }); + + vecShapes.push_back({ Triangle{{ {50.0f, 100.0f}, {10.0f, 150.0f}, {90.0f, 150.0f}} }}); + vecShapes.push_back({ Triangle{{ {350.0f, 200.0f}, {500.0f, 150.0f}, {450.0f, 400.0f}} }}); vecShapes.push_back({ Polygon{{ {60.0f, 420.0f}, {10.0f, 370.0f}, {160.0f, 320.0f}, {210.f, 420.0f}, {160.0f, 470.0f}, {10.0f, 470.0f} }} }); return true; From 3dcf3204efdc933942e63e6a2f7ab9722953e8ad Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 21:18:09 +1200 Subject: [PATCH 05/15] Updated test so that shapes can hit themselves --- TEST_Geometry2D.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index 97c80ed..f8c163d 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -416,9 +416,6 @@ class Test_Geometry2D : public olc::PixelGameEngine for (size_t i = 0; i < vecShapes.size(); i++) { - // Dont check against origin shape - if (i == last_hit_index) continue; - const auto& vTargetShape = vecShapes[i]; auto hit = CheckReflect(ray_laser, vTargetShape); if (hit.has_value()) @@ -437,6 +434,7 @@ class Test_Geometry2D : public olc::PixelGameEngine { DrawLine(ray_laser.origin, ray_reflected.origin, olc::Pixel(rand() % 155 + 100, 0, 0)); ray_laser = ray_reflected; + ray_laser.origin += ray_reflected.direction * 0.01f; ray_stop = false; last_hit_index = closest_hit_index; nBounces--; From fa5b2225a746ba47494f0236e7ea5b4a3780ec95 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 21:39:14 +1200 Subject: [PATCH 06/15] Fixed contains line method --- olcUTIL_Geometry2D.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index efc85a4..fd2a486 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -1381,6 +1381,25 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const polygon& p, const line& l) { + line l2; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l2 = { p.pos[i], p.pos[0] }; + } + else + { + l2 = { p.pos[i], p.pos[i + 1] }; + } + + if (overlaps(l, l2) == true) + { + return false; + } + } + return contains(p, l.start) && contains(p, l.end); } From 8b326d0f6d826d7fd82ffb6f4c40bdb8a182c507 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 21:44:22 +1200 Subject: [PATCH 07/15] Fixed circle contains functions --- olcUTIL_Geometry2D.h | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index fd2a486..c08b97e 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -1896,7 +1896,26 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const polygon& p, const circle& c) { - return false; + line l; + + for (size_t i = 0; i < p.pos.size(); i++) + { + if (i == p.pos.size() - 1) + { + l = { p.pos[i], p.pos[0] }; + } + else + { + l = { p.pos[i], p.pos[i + 1] }; + } + + if (overlaps(l, c) == true) + { + return false; + } + } + + return contains(p, c.pos); } @@ -3030,13 +3049,13 @@ namespace olc::utils::geom2d { for (auto& triangle : p.triangles) { - if (contains(triangle, c) == true) + if (contains(triangle, c) == false) { - return true; + return false; } } - return false; + return true; } // contains(t,p) From 811d4820d0e123201a090af6149a2b352bec52c9 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 21:51:21 +1200 Subject: [PATCH 08/15] Fixed up other contains functions --- olcUTIL_Geometry2D.h | 48 ++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index c08b97e..f9c65e2 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2985,13 +2985,13 @@ namespace olc::utils::geom2d { for (auto& triangle : p1.triangles) { - if (contains(triangle, p2) == true) + if (contains(triangle, p2) == false) { - return true; + return false; } } - return false; + return true; } // contains(p,p) @@ -2999,14 +2999,6 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const olc::v_2d& p1, const polygon& p2) { - for (auto& triangle : p2.triangles) - { - if (contains(triangle, p1) == true) - { - return true; - } - } - return false; } @@ -3015,14 +3007,6 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const line& l, const polygon& p) { - for (auto& triangle : p.triangles) - { - if (contains(triangle, l) == true) - { - return true; - } - } - return false; } @@ -3033,13 +3017,13 @@ namespace olc::utils::geom2d { for (auto& triangle : p.triangles) { - if (contains(triangle, r) == true) + if (contains(r, triangle) == false) { - return true; + return false; } } - return false; + return true; } // contains(c,p) @@ -3049,7 +3033,7 @@ namespace olc::utils::geom2d { for (auto& triangle : p.triangles) { - if (contains(triangle, c) == false) + if (contains(c, triangle) == false) { return false; } @@ -3065,21 +3049,29 @@ namespace olc::utils::geom2d { for (auto& triangle : p.triangles) { - if (contains(triangle, t) == true) + if (contains(t, triangle) == false) { - return true; + return false; } } - return false; + return true; } - // contains(t,p) + // contains(p,p) // Checks if polygon contains polygon template inline constexpr bool contains(const polygon& p1, const polygon& p2) { - return false; + for (auto& triangle : p1.triangles) + { + if (contains(p2, triangle) == false) + { + return false; + } + } + + return true; } // intersects(p,p) From bbf7c148db56b55c939c29625d0f921cb075244d Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Mon, 13 May 2024 22:21:54 +1200 Subject: [PATCH 09/15] Added ability to to see polygon triangles --- TEST_Geometry2D.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index f8c163d..39a973d 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -226,6 +226,7 @@ class Test_Geometry2D : public olc::PixelGameEngine void draw_internal(const Polygon& p, const olc::Pixel col) { const auto t = make_internal(p); + for (size_t i = 0; i < t.pos.size(); i++) { if (i == t.pos.size() - 1) @@ -237,6 +238,14 @@ class Test_Geometry2D : public olc::PixelGameEngine DrawLine(t.pos[i], t.pos[i + 1], col); } } + + if (bShowPolygonTriangles == true) + { + for (auto& triangle : t.triangles) + { + DrawTriangle(triangle.pos[0], triangle.pos[1], triangle.pos[2], col); + } + } } void DrawShape(const ShapeWrap& shape, const olc::Pixel col = olc::WHITE) @@ -251,6 +260,7 @@ class Test_Geometry2D : public olc::PixelGameEngine size_t nSelectedShapeIndex = -1; olc::vi2d vOldMousePos; + bool bShowPolygonTriangles = false; public: bool OnUserCreate() override @@ -268,7 +278,7 @@ class Test_Geometry2D : public olc::PixelGameEngine vecShapes.push_back({ Triangle{{ {50.0f, 100.0f}, {10.0f, 150.0f}, {90.0f, 150.0f}} }}); vecShapes.push_back({ Triangle{{ {350.0f, 200.0f}, {500.0f, 150.0f}, {450.0f, 400.0f}} }}); - vecShapes.push_back({ Polygon{{ {60.0f, 420.0f}, {10.0f, 370.0f}, {160.0f, 320.0f}, {210.f, 420.0f}, {160.0f, 470.0f}, {10.0f, 470.0f} }} }); + vecShapes.push_back({ Polygon{{ {60.0f, 420.0f}, {10.0f, 370.0f}, {160.0f, 320.0f}, {210.f, 420.0f}, {160.0f, 470.0f}, {30.0f, 470.0f} }} }); return true; } @@ -277,6 +287,11 @@ class Test_Geometry2D : public olc::PixelGameEngine { Clear(olc::VERY_DARK_BLUE); + if (GetKey(olc::Key::SPACE).bPressed == true) + { + bShowPolygonTriangles = !bShowPolygonTriangles; + } + olc::vf2d vMouseDelta = GetMousePos() - vOldMousePos; vOldMousePos = GetMousePos(); From e7c23f96fa42b8dfc0e7a34071e69c94d7de1f30 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Tue, 14 May 2024 12:51:53 +1200 Subject: [PATCH 10/15] Update olcUTIL_Geometry2D.h Removed unnecessary cross --- olcUTIL_Geometry2D.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index f9c65e2..4c06db7 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2896,7 +2896,7 @@ namespace olc::utils::geom2d olc::v_2d pb_pa = points[b] - points[a]; olc::v_2d pc_pa = points[c] - points[a]; - float cross = pb_pa.cross(pc_pa); + if (pb_pa.cross(pc_pa) > 0.0f) { continue; From d7df193c0cbde53f748097aa800d4186e87ff40f Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Wed, 15 May 2024 21:45:35 +1200 Subject: [PATCH 11/15] Polygon stores edges --- olcUTIL_Geometry2D.h | 193 +++++++++---------------------------------- 1 file changed, 40 insertions(+), 153 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index f9c65e2..14e6715 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -793,6 +793,8 @@ namespace olc::utils::geom2d // triangles that make up the polygon std::vector> triangles; + + std::vector> edges; }; @@ -1381,20 +1383,9 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const polygon& p, const line& l) { - line l2; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - if (overlaps(l, l2) == true) + if (overlaps(l, edge) == true) { return false; } @@ -1582,21 +1573,11 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const line& l) { - line l2; std::vector> intersections; - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(l, l2); + auto v = intersects(l, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -1812,21 +1793,11 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const rect& r) { - line l2; std::vector> intersections; - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(r, l2); + auto v = intersects(r, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -1896,20 +1867,9 @@ namespace olc::utils::geom2d template inline constexpr bool contains(const polygon& p, const circle& c) { - line l; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l = { p.pos[i], p.pos[0] }; - } - else - { - l = { p.pos[i], p.pos[i + 1] }; - } - - if (overlaps(l, c) == true) + if (overlaps(c, edge) == true) { return false; } @@ -2067,21 +2027,11 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const circle& c) { - line l2; std::vector> intersections; - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(c, l2); + auto v = intersects(c, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -2274,21 +2224,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon& p, const triangle& t) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(t, l2); + auto v = intersects(t, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -2879,6 +2818,20 @@ namespace olc::utils::geom2d { indexList.push_back(i); returnPolygon.pos.push_back(points[i]); + line edge; + + if (i == points.size() - 1) + { + edge.start = points[i]; + edge.end = points[0]; + } + else + { + edge.start = points[i]; + edge.end = points[i + 1]; + } + + returnPolygon.edges.push_back(edge); } while (indexList.size() > 3) @@ -3095,21 +3048,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const line l, const polygon& p) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(l2, l); + auto v = intersects(l, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -3121,21 +3063,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const rect r, const polygon& p) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(l2, r); + auto v = intersects(r, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -3147,21 +3078,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const circle c, const polygon& p) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(l2, c); + auto v = intersects(c, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -3173,21 +3093,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const triangle t, const polygon& p) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(l2, t); + auto v = intersects(t, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -3199,21 +3108,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const polygon p1, const polygon& p2) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p2.pos.size(); i++) + for (auto& edge : p2.edges) { - if (i == p2.pos.size() - 1) - { - l2 = { p2.pos[i], p2.pos[0] }; - } - else - { - l2 = { p2.pos[i], p2.pos[i + 1] }; - } - - auto v = intersects(l2, p1); + auto v = intersects(p1, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } @@ -3227,21 +3125,10 @@ namespace olc::utils::geom2d template inline std::vector> intersects(const ray& r, const polygon& p) { - line l2; std::vector> intersections; - - for (size_t i = 0; i < p.pos.size(); i++) + for (auto& edge : p.edges) { - if (i == p.pos.size() - 1) - { - l2 = { p.pos[i], p.pos[0] }; - } - else - { - l2 = { p.pos[i], p.pos[i + 1] }; - } - - auto v = intersects(r, l2); + auto v = intersects(r, edge); intersections.insert(intersections.end(), v.begin(), v.end()); } From 89920b4f93f43f8b8d46a29f6a13daa31816cb17 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Thu, 16 May 2024 14:33:30 +1200 Subject: [PATCH 12/15] Returns an empty polygon if there are not enough points Points can be CCW or CW --- olcUTIL_Geometry2D.h | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index 2ed384a..2a28d2d 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2812,12 +2812,23 @@ namespace olc::utils::geom2d { polygon returnPolygon; + // Less than three points so return empty polygpon + if (points.size() < 3) + { + return returnPolygon; + } + std::vector indexList; + float area = 0.0; + for (size_t i = 0; i < points.size(); i++) { indexList.push_back(i); returnPolygon.pos.push_back(points[i]); + size_t j = (i + 1) % points.size(); + area += points[i].x * points[j].y - points[j].x * points[i].y; + line edge; if (i == points.size() - 1) @@ -2834,6 +2845,12 @@ namespace olc::utils::geom2d returnPolygon.edges.push_back(edge); } + if (area < 0.0f) + { + std::reverse(returnPolygon.pos.begin(), returnPolygon.pos.end()); + std::reverse(returnPolygon.edges.begin(), returnPolygon.edges.end()); + } + while (indexList.size() > 3) { for (size_t i = 0; i < indexList.size(); i++) @@ -2843,12 +2860,12 @@ namespace olc::utils::geom2d size_t c = indexList[i == indexList.size() - 1 ? 0 : i + 1]; triangle thisTriangle; - thisTriangle.pos[0] = points[a]; - thisTriangle.pos[1] = points[b]; - thisTriangle.pos[2] = points[c]; + thisTriangle.pos[0] = returnPolygon.pos[a]; + thisTriangle.pos[1] = returnPolygon.pos[b]; + thisTriangle.pos[2] = returnPolygon.pos[c]; - olc::v_2d pb_pa = points[b] - points[a]; - olc::v_2d pc_pa = points[c] - points[a]; + olc::v_2d pb_pa = returnPolygon.pos[b] - returnPolygon.pos[a]; + olc::v_2d pc_pa = returnPolygon.pos[c] - returnPolygon.pos[a]; if (pb_pa.cross(pc_pa) > 0.0f) { @@ -2857,14 +2874,14 @@ namespace olc::utils::geom2d bool isEar = true; - for (size_t j = 0; j < points.size(); j++) + for (size_t j = 0; j < returnPolygon.pos.size(); j++) { if (j == a || j == b || j == c) { continue; } - if (contains(thisTriangle, points[j]) == true) + if (contains(thisTriangle, returnPolygon.pos[j]) == true) { isEar = false; break; @@ -2882,9 +2899,9 @@ namespace olc::utils::geom2d } triangle lastTriangle; - lastTriangle.pos[0] = points[indexList[0]]; - lastTriangle.pos[1] = points[indexList[1]]; - lastTriangle.pos[2] = points[indexList[2]]; + lastTriangle.pos[0] = returnPolygon.pos[indexList[0]]; + lastTriangle.pos[1] = returnPolygon.pos[indexList[1]]; + lastTriangle.pos[2] = returnPolygon.pos[indexList[2]]; returnPolygon.triangles.push_back(lastTriangle); From cd921a870328ff5edd6bf23a4d841744e5968c20 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:11:20 +1200 Subject: [PATCH 13/15] Added float triangle for angle testing --- olcUTIL_Geometry2D.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index 2a28d2d..e81d317 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2851,7 +2851,9 @@ namespace olc::utils::geom2d std::reverse(returnPolygon.edges.begin(), returnPolygon.edges.end()); } - while (indexList.size() > 3) + uint32_t loopCounter = 1000; + + while (indexList.size() > 3 && loopCounter > 0) { for (size_t i = 0; i < indexList.size(); i++) { @@ -2864,10 +2866,10 @@ namespace olc::utils::geom2d thisTriangle.pos[1] = returnPolygon.pos[b]; thisTriangle.pos[2] = returnPolygon.pos[c]; - olc::v_2d pb_pa = returnPolygon.pos[b] - returnPolygon.pos[a]; - olc::v_2d pc_pa = returnPolygon.pos[c] - returnPolygon.pos[a]; + vf2d pb_pa = returnPolygon.pos[b] - returnPolygon.pos[a]; + vf2d pc_pa = returnPolygon.pos[c] - returnPolygon.pos[a]; - if (pb_pa.cross(pc_pa) > 0.0f) + if (pb_pa.x * pc_pa.y - pb_pa.y * pc_pa.x > 0.0f) { continue; } @@ -2881,7 +2883,8 @@ namespace olc::utils::geom2d continue; } - if (contains(thisTriangle, returnPolygon.pos[j]) == true) + triangle fTriangle(thisTriangle.pos[0], thisTriangle.pos[1], thisTriangle.pos[2]); + if (contains(fTriangle, vf2d(returnPolygon.pos[j])) == true) { isEar = false; break; @@ -2896,6 +2899,8 @@ namespace olc::utils::geom2d break; } } + + loopCounter--; } triangle lastTriangle; From 027109b64e25f38f44a80cbe32ee4325511208e7 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:38:15 +1200 Subject: [PATCH 14/15] Fixed polygon overlap functions --- olcUTIL_Geometry2D.h | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index e81d317..8ae0d6b 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2926,7 +2926,15 @@ namespace olc::utils::geom2d template inline constexpr bool overlaps(const line& l, const polygon& p) { - return contains(l, p); + for (auto& triangle : p.triangles) + { + if (overlaps(l, triangle) == true) + { + return true; + } + } + + return false; } // overlaps(r,p) @@ -2934,7 +2942,15 @@ namespace olc::utils::geom2d template inline constexpr bool overlaps(const rect& r, const polygon& p) { - return contains(r, p); + for (auto& triangle : p.triangles) + { + if (overlaps(r, triangle) == true) + { + return true; + } + } + + return false; } // overlaps(c,p) @@ -2942,7 +2958,15 @@ namespace olc::utils::geom2d template inline constexpr bool overlaps(const circle& c, const polygon& p) { - return contains(c, p); + for (auto& triangle : p.triangles) + { + if (overlaps(c, triangle) == true) + { + return true; + } + } + + return false; } // overlaps(t,p) @@ -2950,7 +2974,15 @@ namespace olc::utils::geom2d template inline constexpr bool overlaps(const triangle& t, const polygon& p) { - return contains(t, p); + for (auto& triangle : p.triangles) + { + if (overlaps(t, triangle) == true) + { + return true; + } + } + + return false; } // overlaps(t,p) @@ -2960,7 +2992,7 @@ namespace olc::utils::geom2d { for (auto& triangle : p1.triangles) { - if (contains(triangle, p2) == false) + if (overlaps(triangle, p2) == false) { return false; } From ad06faf41469dca58a8d7d9cf9f7a039e1471238 Mon Sep 17 00:00:00 2001 From: gamecoder-nz <42922238+gamecoder-nz@users.noreply.github.com> Date: Tue, 3 Sep 2024 19:48:21 +1200 Subject: [PATCH 15/15] Fixed polygon polygon test --- olcUTIL_Geometry2D.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index c772a12..5f6c23e 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -3019,13 +3019,13 @@ namespace olc::utils::geom2d { for (auto& triangle : p1.triangles) { - if (overlaps(triangle, p2) == false) + if (overlaps(triangle, p2) == true) { - return false; + return true; } } - return true; + return false; } // contains(p,p)