diff --git a/u02/include/util.h b/u02/include/util.h index b1e1574..383034e 100644 --- a/u02/include/util.h +++ b/u02/include/util.h @@ -39,3 +39,7 @@ std::tuple barycentric_coordinates(int x0, int y0, int x1, // Sorts the points of a triangle to be in ascending order (y0 < y1 < y2). void sort_triangle_points(int &x0, int &y0, int &x1, int &y1, int &x2, int &y2); + +// This calculates the slope of a line from (x0, y0) to (x1, y1). +// It handles special cases to ensure the return value will be real. +float slope(int x0, int y0, int x1, int y1); diff --git a/u02/src/tests.cpp b/u02/src/tests.cpp index ce03ca0..87e541e 100644 --- a/u02/src/tests.cpp +++ b/u02/src/tests.cpp @@ -452,3 +452,16 @@ TEST_CASE("Sort triangle points (prop: y0 < y1 < y2)") { REQUIRE(y0 <= y1); REQUIRE(y1 <= y2); } + +TEST_CASE("Slope") { + REQUIRE(slope(5, 10, 20, 10) == 0.0); + REQUIRE(slope(0, 0, 10, 10) == 1.0); + REQUIRE(slope(0, 0, 10, -10) == -1.0); + REQUIRE(slope(0, 0, 10, 5) == 0.5); + REQUIRE(slope(0, 0, 10, -5) == -0.5); + REQUIRE(slope(0, 10, 10, 40) == 3.0); + REQUIRE(slope(0, 10, 10, -40) == -5.0); + + // Special case: Infinite slope, must be normalized + REQUIRE(slope(10, 10, 10, 40) == 0.0); +} diff --git a/u02/src/util.cpp b/u02/src/util.cpp index 3c991b3..5ed7266 100644 --- a/u02/src/util.cpp +++ b/u02/src/util.cpp @@ -180,3 +180,19 @@ void sort_triangle_points(int &x0, int &y0, int &x1, int &y1, int &x2, std::swap(y1, y2); } } + +float slope(int x0, int y0, int x1, int y1) { + float m = ((float)(y1 - y0)) / ((float)(x1 - x0)); + if (std::isinf(m) || std::isnan(m)) { + // This is a special case for two things: + // + // IEEE 754 specifies ∞ × 0 / 0 × ∞ to be an invalid operation, + // and therefore return NaN. + // That makes the computation of Δy fail when x0 == x1. + // + // In the case that additionally y0 == y1, + // the expression is 0/0, also defined in IEEE 754 as invalid. + m = 0; + } + return m; +}