Files
ViewDesignEngine/tests/core/test_polygon.cpp
T

147 lines
4.4 KiB
C++
Raw Normal View History

2026-07-23 12:36:39 +00:00
#include <gtest/gtest.h>
#include "vde/core/polygon.h"
using namespace vde::core;
// ── signed_area tests ──
TEST(PolygonTest, SignedArea_CCWSquare_Positive) {
// Counter-clockwise unit square
Polygon2D poly({{0, 0}, {1, 0}, {1, 1}, {0, 1}});
EXPECT_GT(poly.signed_area(), 0.0);
EXPECT_NEAR(poly.signed_area(), 1.0, 1e-9);
}
TEST(PolygonTest, SignedArea_CWSquare_Negative) {
// Clockwise unit square
Polygon2D poly({{0, 0}, {0, 1}, {1, 1}, {1, 0}});
EXPECT_LT(poly.signed_area(), 0.0);
EXPECT_NEAR(poly.signed_area(), -1.0, 1e-9);
}
TEST(PolygonTest, SignedArea_Triangle) {
Polygon2D poly({{0, 0}, {3, 0}, {0, 4}});
EXPECT_NEAR(std::abs(poly.signed_area()), 6.0, 1e-9);
}
TEST(PolygonTest, SignedArea_Collinear_Degenerate) {
// All points on a line → zero area
Polygon2D poly({{0, 0}, {1, 1}, {2, 2}});
EXPECT_NEAR(poly.signed_area(), 0.0, 1e-9);
}
TEST(PolygonTest, SignedArea_Empty) {
Polygon2D poly;
EXPECT_DOUBLE_EQ(poly.signed_area(), 0.0);
}
TEST(PolygonTest, Area_AbsoluteValue) {
// area() should be absolute value of signed_area()
Polygon2D ccw({{0, 0}, {2, 0}, {2, 2}, {0, 2}});
Polygon2D cw({{0, 0}, {0, 2}, {2, 2}, {2, 0}});
EXPECT_NEAR(ccw.area(), 4.0, 1e-9);
EXPECT_NEAR(cw.area(), 4.0, 1e-9);
}
// ── contains (point-in-polygon via ray casting) ──
TEST(PolygonTest, Contains_InteriorPoint) {
Polygon2D square({{0, 0}, {2, 0}, {2, 2}, {0, 2}});
// Center of the square
EXPECT_TRUE(square.contains(Point2D(1.0, 1.0)));
}
TEST(PolygonTest, Contains_ExteriorPoint) {
Polygon2D square({{0, 0}, {2, 0}, {2, 2}, {0, 2}});
// Far outside
EXPECT_FALSE(square.contains(Point2D(10.0, 10.0)));
// Outside but near
EXPECT_FALSE(square.contains(Point2D(-0.1, 1.0)));
}
TEST(PolygonTest, Contains_BoundaryPoint) {
Polygon2D square({{0, 0}, {2, 0}, {2, 2}, {0, 2}});
// On edge — behavior may vary; ray casting treats as intersection
// Not strictly "interior" in most implementations
Point2D on_edge(1.0, 0.0);
// Just verify it doesn't crash; boundary is valid input
bool result = square.contains(on_edge);
(void)result; // implementation-defined for boundary
SUCCEED();
}
TEST(PolygonTest, Contains_PointOnVertex) {
Polygon2D tri({{0, 0}, {2, 0}, {0, 2}});
// Exact vertex — should not crash
bool result = tri.contains(Point2D(0.0, 0.0));
(void)result;
SUCCEED();
}
TEST(PolygonTest, Contains_ConcavePolygon) {
// L-shaped polygon (concave)
Polygon2D L({{0, 0}, {3, 0}, {3, 1}, {2, 1}, {2, 3}, {0, 3}});
// Point in the "notch" area (1.5, 2) should be inside
EXPECT_TRUE(L.contains(Point2D(1.0, 2.0)));
// Point in the concave void
EXPECT_FALSE(L.contains(Point2D(2.5, 2.0)));
}
// ── is_ccw ──
TEST(PolygonTest, IsCCW) {
Polygon2D ccw({{0, 0}, {1, 0}, {1, 1}, {0, 1}});
Polygon2D cw({{0, 0}, {0, 1}, {1, 1}, {1, 0}});
EXPECT_TRUE(ccw.is_ccw());
EXPECT_FALSE(cw.is_ccw());
}
// ── Basic accessors ──
TEST(PolygonTest, SizeAndEmpty) {
Polygon2D empty;
EXPECT_TRUE(empty.empty());
EXPECT_EQ(empty.size(), 0u);
Polygon2D tri({{0, 0}, {1, 0}, {0, 1}});
EXPECT_FALSE(tri.empty());
EXPECT_EQ(tri.size(), 3u);
}
TEST(PolygonTest, VerticesAccessor) {
std::vector<Point2D> v = {{0, 0}, {1, 0}, {0, 1}};
Polygon2D poly(v);
EXPECT_EQ(poly.vertices().size(), 3u);
EXPECT_DOUBLE_EQ(poly.vertices()[0].x(), 0.0);
EXPECT_DOUBLE_EQ(poly.vertices()[1].y(), 0.0);
}
TEST(PolygonTest, DefaultConstructor_Empty) {
Polygon2D poly;
EXPECT_TRUE(poly.vertices().empty());
EXPECT_TRUE(poly.empty());
}
// ── Larger polygon area (regular hexagon) ──
TEST(PolygonTest, SignedArea_RegularHexagon) {
// Regular hexagon centered at origin, radius 1
// Vertices CCW: (1,0), (0.5,0.866), (-0.5,0.866), (-1,0), (-0.5,-0.866), (0.5,-0.866)
Polygon2D hex({
{1.0, 0.0}, {0.5, std::sqrt(3.0) / 2.0},
{-0.5, std::sqrt(3.0) / 2.0}, {-1.0, 0.0},
{-0.5, -std::sqrt(3.0) / 2.0}, {0.5, -std::sqrt(3.0) / 2.0}
});
// Area of regular hexagon = (3√3 / 2) * r² ≈ 2.598
EXPECT_NEAR(hex.signed_area(), 3.0 * std::sqrt(3.0) / 2.0, 1e-9);
}
TEST(PolygonTest, Contains_StarShapedHexagon) {
Polygon2D hex({
{1.0, 0.0}, {0.5, 0.866}, {-0.5, 0.866},
{-1.0, 0.0}, {-0.5, -0.866}, {0.5, -0.866}
});
EXPECT_TRUE(hex.contains(Point2D(0.0, 0.0)));
EXPECT_FALSE(hex.contains(Point2D(2.0, 0.0)));
}