diff --git a/u02/include/util.h b/u02/include/util.h index 383034e..113520d 100644 --- a/u02/include/util.h +++ b/u02/include/util.h @@ -33,6 +33,7 @@ Transformation transformation_to_standard_case(int x0, int y0, int x1, int y1); // Returns the barycentric coordinates of the point given by (xp, yp) // in the triangle given by the three points (x0, y0), (x1, y1), (x2, y2). +// May return non-real values when the points are on a straight line. std::tuple barycentric_coordinates(int x0, int y0, int x1, int y1, int x2, int y2, int xp, int yp); diff --git a/u02/src/tests.cpp b/u02/src/tests.cpp index 87e541e..22c028b 100644 --- a/u02/src/tests.cpp +++ b/u02/src/tests.cpp @@ -409,6 +409,17 @@ TEST_CASE("Barycentric coordinates: Edge cases") { REQUIRE(b1 == 0); REQUIRE(b2 == 0.5); REQUIRE(b3 == 0.5); + + // All points on straight line + std::tie(b1, b2, b3) = barycentric_coordinates(0, y0, 0, y1, 0, y2, 0, 0); + REQUIRE(std::isnan(b1)); + REQUIRE(std::isnan(b2)); + REQUIRE(std::isnan(b3)); + + std::tie(b1, b2, b3) = barycentric_coordinates(x0, 0, x1, 0, x2, 0, 0, 0); + REQUIRE(std::isnan(b1)); + REQUIRE(std::isnan(b2)); + REQUIRE(std::isnan(b3)); } TEST_CASE("Barycentric coordinates (prop: Σ = 1)") { @@ -425,7 +436,10 @@ TEST_CASE("Barycentric coordinates (prop: Σ = 1)") { std::tie(b1, b2, b3) = barycentric_coordinates(x0, y0, x1, y1, x2, y2, x, y); - REQUIRE_THAT(b1 + b2 + b3, WithinRel(1.0, 1e-4)); + // If all points are on a straight line, the property does not hold + if (!(x0 == x1 && x1 == x2) && !(y0 == y1 && y1 == y2)) { + REQUIRE_THAT(b1 + b2 + b3, WithinRel(1.0, 1e-4)); + } } TEST_CASE("Sort triangle points") {