diff --git a/SDL2pp/Rect.cc b/SDL2pp/Rect.cc index d04f598..252dfad 100644 --- a/SDL2pp/Rect.cc +++ b/SDL2pp/Rect.cc @@ -197,6 +197,14 @@ Optional Rect::GetIntersection(const Rect& rect) const { ); } +bool Rect::IntersectLine(int& x1, int& y1, int& x2, int& y2) const { + return SDL_IntersectRectAndLine(this, &x1, &y1, &x2, &y2) == SDL_TRUE; +} + +bool Rect::IntersectLine(Point& p1, Point& p2) const { + return SDL_IntersectRectAndLine(this, &p1.x, &p1.y, &p2.x, &p2.y) == SDL_TRUE; +} + Rect Rect::operator+(const Point& offset) const { return Rect(x + offset.x, y + offset.y, w, h); } diff --git a/SDL2pp/Rect.hh b/SDL2pp/Rect.hh index 79f7139..1bde8fc 100644 --- a/SDL2pp/Rect.hh +++ b/SDL2pp/Rect.hh @@ -376,6 +376,45 @@ public: //////////////////////////////////////////////////////////// Optional GetIntersection(const Rect& rect) const; + //////////////////////////////////////////////////////////// + /// \brief Calculate the intersection of a rectangle and line segment + /// + /// \param[in,out] x1 Starting X-coordinate of the line + /// \param[in,out] y1 Starting Y-coordinate of the line + /// \param[in,out] x2 Ending X-coordinate of the line + /// \param[in,out] y2 Ending Y-coordinate of the line + /// + /// \returns True if there is an intersection, false otherwise + /// + /// This function is used to clip a line segment to a + /// rectangle. A line segment contained entirely within the + /// rectangle or that does not intersect will remain unchanged. + /// A line segment that crosses the rectangle at either or both + /// ends will be clipped to the boundary of the rectangle and + /// the new coordinates saved in x1, y1, x2, and/or y2 as + /// necessary. + /// + //////////////////////////////////////////////////////////// + bool IntersectLine(int& x1, int& y1, int& x2, int& y2) const; + + //////////////////////////////////////////////////////////// + /// \brief Calculate the intersection of a rectangle and line segment + /// + /// \param[in,out] p1 Starting coordinates of the line + /// \param[in,out] p2 Ending coordinates of the line + /// + /// \returns True if there is an intersection, false otherwise + /// + /// This function is used to clip a line segment to a + /// rectangle. A line segment contained entirely within the + /// rectangle or that does not intersect will remain unchanged. + /// A line segment that crosses the rectangle at either or both + /// ends will be clipped to the boundary of the rectangle and + /// the new coordinates saved in p1 and/or p2 as necessary. + /// + //////////////////////////////////////////////////////////// + bool IntersectLine(Point& p1, Point& p2) const; + //////////////////////////////////////////////////////////// /// \brief Get rectangle moved by a given offset /// diff --git a/tests/test_pointrect.cc b/tests/test_pointrect.cc index bb38842..3585ed6 100644 --- a/tests/test_pointrect.cc +++ b/tests/test_pointrect.cc @@ -240,6 +240,23 @@ BEGIN_TEST() EXPECT_TRUE(Rect(30, 40, 1, 1).Union(Rect(10, 20, 1, 1)) == Rect::FromCorners(10, 20, 30, 40)); } + { + // Rect/line intersections + Rect rect = Rect::FromCorners(10, 10, 20, 20); + + Point p1(0, 0), p2(30, 30); + EXPECT_TRUE(rect.IntersectLine(p1, p2)); + EXPECT_TRUE(p1 == Point(10, 10)); + EXPECT_TRUE(p2 == Point(20, 20)); + + int x1 = 30, y1 = 0, x2 = 0, y2 = 30; + EXPECT_TRUE(rect.IntersectLine(x1, y1, x2, y2)); + EXPECT_TRUE(x1 == 20); + EXPECT_TRUE(y1 == 10); + EXPECT_TRUE(x2 == 10); + EXPECT_TRUE(y2 == 20); + } + { // Rect extend EXPECT_TRUE(Rect(10, 20, 30, 40).GetExtension(0) == Rect(10, 20, 30, 40));