# HG changeset patch # User Sebastien Jodogne # Date 1643664751 -3600 # Node ID 925aaf49150c12fdccbbc944b8e1e29711446093 # Parent e318b524ad3f2fe8114e4044b84b4f980646331c minor fix in UnionOfRectangles diff -r e318b524ad3f -r 925aaf49150c OrthancStone/Sources/Toolbox/UnionOfRectangles.cpp --- a/OrthancStone/Sources/Toolbox/UnionOfRectangles.cpp Mon Jan 31 18:50:35 2022 +0100 +++ b/OrthancStone/Sources/Toolbox/UnionOfRectangles.cpp Mon Jan 31 22:32:31 2022 +0100 @@ -211,7 +211,7 @@ { if (stack.size() % 2 != 0) { - throw std::runtime_error("internal error"); + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } typedef std::pair Interval; @@ -224,7 +224,7 @@ stack.pop(); size_t low = stack.top(); stack.pop(); - + if (!intervals.empty() && intervals.back().second == low) { @@ -240,19 +240,43 @@ for (std::list::const_iterator it = intervals.begin(); it != intervals.end(); ++it) { - if (it->first == it->second) + if (it->first >= it->second) { - throw std::runtime_error("parameter out of range"); + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } // By convention, the left sides go downward, and the right go upward if (isLeft) { - edges.push_back(Internals::OrientedIntegerLine2D(x, it->first, x, it->second)); + if (!edges.empty() && + edges.back().GetX1() == x && + edges.back().GetX2() == x && + edges.back().GetY1() == it->second && + edges.back().GetY2() == it->first) + { + // The two successive vertical segments cancel each other + edges.pop_back(); + } + else + { + edges.push_back(Internals::OrientedIntegerLine2D(x, it->first, x, it->second)); + } } else { - edges.push_back(Internals::OrientedIntegerLine2D(x, it->second, x, it->first)); + if (!edges.empty() && + edges.back().GetX1() == x && + edges.back().GetX2() == x && + edges.back().GetY1() == it->first && + edges.back().GetY2() == it->second) + { + // The two successive vertical segments cancel each other + edges.pop_back(); + } + else + { + edges.push_back(Internals::OrientedIntegerLine2D(x, it->second, x, it->first)); + } } } } diff -r e318b524ad3f -r 925aaf49150c OrthancStone/UnitTestsSources/ComputationalGeometryTests.cpp --- a/OrthancStone/UnitTestsSources/ComputationalGeometryTests.cpp Mon Jan 31 18:50:35 2022 +0100 +++ b/OrthancStone/UnitTestsSources/ComputationalGeometryTests.cpp Mon Jan 31 22:32:31 2022 +0100 @@ -561,9 +561,33 @@ fprintf(fp, "\n", ww, hh); + unsigned int count = 0; + for (std::list< std::vector >::const_iterator - it = contours.begin(); it != contours.end(); ++it) + it = contours.begin(); it != contours.end(); ++it, count++) { + std::string color; + if (count == 0) + { + color = "blue"; + } + else if (count == 1) + { + color = "red"; + } + else if (count == 2) + { + color = "green"; + } + else if (count == 3) + { + color = "orange"; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } + for (size_t i = 0; i + 1 < it->size(); i++) { float x1 = (*it)[i].GetX(); @@ -571,7 +595,7 @@ float y1 = (*it)[i].GetY(); float y2 = (*it)[i + 1].GetY(); - fprintf(fp, "\n", x1, y1, x2, y2); + fprintf(fp, "\n", x1, y1, x2, y2, color.c_str()); } } fprintf(fp, "\n"); @@ -653,25 +677,29 @@ std::list< std::vector > contours; OrthancStone::UnionOfRectangles::Apply(contours, rectangles); - ASSERT_EQ(1u, contours.size()); - ASSERT_EQ(17u, contours.front().size()); + ASSERT_EQ(2u, contours.size()); + + ASSERT_EQ(9u, contours.front().size()); ASSERT_TRUE(contours.front()[0].IsEqual(OrthancStone::ScenePoint2D(4, 8))); ASSERT_TRUE(contours.front()[1].IsEqual(OrthancStone::ScenePoint2D(7, 8))); ASSERT_TRUE(contours.front()[2].IsEqual(OrthancStone::ScenePoint2D(7, 6))); ASSERT_TRUE(contours.front()[3].IsEqual(OrthancStone::ScenePoint2D(10, 6))); ASSERT_TRUE(contours.front()[4].IsEqual(OrthancStone::ScenePoint2D(10, 4))); ASSERT_TRUE(contours.front()[5].IsEqual(OrthancStone::ScenePoint2D(7, 4))); - ASSERT_TRUE(contours.front()[6].IsEqual(OrthancStone::ScenePoint2D(7, 2))); - ASSERT_TRUE(contours.front()[7].IsEqual(OrthancStone::ScenePoint2D(4, 2))); - ASSERT_TRUE(contours.front()[8].IsEqual(OrthancStone::ScenePoint2D(4, 4))); - ASSERT_TRUE(contours.front()[9].IsEqual(OrthancStone::ScenePoint2D(7, 4))); - ASSERT_TRUE(contours.front()[10].IsEqual(OrthancStone::ScenePoint2D(7, 6))); - ASSERT_TRUE(contours.front()[11].IsEqual(OrthancStone::ScenePoint2D(4, 6))); - ASSERT_TRUE(contours.front()[12].IsEqual(OrthancStone::ScenePoint2D(4, 4))); - ASSERT_TRUE(contours.front()[13].IsEqual(OrthancStone::ScenePoint2D(1, 4))); - ASSERT_TRUE(contours.front()[14].IsEqual(OrthancStone::ScenePoint2D(1, 6))); - ASSERT_TRUE(contours.front()[15].IsEqual(OrthancStone::ScenePoint2D(4, 6))); - ASSERT_TRUE(contours.front()[16].IsEqual(OrthancStone::ScenePoint2D(4, 8))); + ASSERT_TRUE(contours.front()[6].IsEqual(OrthancStone::ScenePoint2D(7, 6))); + ASSERT_TRUE(contours.front()[7].IsEqual(OrthancStone::ScenePoint2D(4, 6))); + ASSERT_TRUE(contours.front()[8].IsEqual(OrthancStone::ScenePoint2D(4, 8))); + + ASSERT_EQ(9u, contours.back().size()); + ASSERT_TRUE(contours.back()[0].IsEqual(OrthancStone::ScenePoint2D(1, 6))); + ASSERT_TRUE(contours.back()[1].IsEqual(OrthancStone::ScenePoint2D(4, 6))); + ASSERT_TRUE(contours.back()[2].IsEqual(OrthancStone::ScenePoint2D(4, 4))); + ASSERT_TRUE(contours.back()[3].IsEqual(OrthancStone::ScenePoint2D(7, 4))); + ASSERT_TRUE(contours.back()[4].IsEqual(OrthancStone::ScenePoint2D(7, 2))); + ASSERT_TRUE(contours.back()[5].IsEqual(OrthancStone::ScenePoint2D(4, 2))); + ASSERT_TRUE(contours.back()[6].IsEqual(OrthancStone::ScenePoint2D(4, 4))); + ASSERT_TRUE(contours.back()[7].IsEqual(OrthancStone::ScenePoint2D(1, 4))); + ASSERT_TRUE(contours.back()[8].IsEqual(OrthancStone::ScenePoint2D(1, 6))); } { @@ -736,7 +764,7 @@ { std::list rectangles; - rectangles.push_back(OrthancStone::Extent2D(1, 4, 4, 6)); + rectangles.push_back(OrthancStone::Extent2D(1, 4, 5, 6)); rectangles.push_back(OrthancStone::Extent2D(6, 4, 9, 6)); rectangles.push_back(OrthancStone::Extent2D(4, 6, 7, 8)); rectangles.push_back(OrthancStone::Extent2D(4, 2, 7, 6)); @@ -763,7 +791,7 @@ { std::list rectangles; - rectangles.push_back(OrthancStone::Extent2D(1, 4, 4, 6)); + rectangles.push_back(OrthancStone::Extent2D(1, 4, 5, 6)); rectangles.push_back(OrthancStone::Extent2D(4, 6, 7, 8)); rectangles.push_back(OrthancStone::Extent2D(4, 2, 7, 6)); @@ -896,17 +924,21 @@ std::list< std::vector > contours; OrthancStone::UnionOfRectangles::Apply(contours, rectangles); - ASSERT_EQ(1u, contours.size()); - ASSERT_EQ(9u, contours.front().size()); + ASSERT_EQ(2u, contours.size()); + + ASSERT_EQ(5u, contours.front().size()); ASSERT_TRUE(contours.front()[0].IsEqual(OrthancStone::ScenePoint2D(3, 4))); ASSERT_TRUE(contours.front()[1].IsEqual(OrthancStone::ScenePoint2D(4, 4))); ASSERT_TRUE(contours.front()[2].IsEqual(OrthancStone::ScenePoint2D(4, 3))); ASSERT_TRUE(contours.front()[3].IsEqual(OrthancStone::ScenePoint2D(3, 3))); - ASSERT_TRUE(contours.front()[4].IsEqual(OrthancStone::ScenePoint2D(3, 2))); - ASSERT_TRUE(contours.front()[5].IsEqual(OrthancStone::ScenePoint2D(2, 2))); - ASSERT_TRUE(contours.front()[6].IsEqual(OrthancStone::ScenePoint2D(2, 3))); - ASSERT_TRUE(contours.front()[7].IsEqual(OrthancStone::ScenePoint2D(3, 3))); - ASSERT_TRUE(contours.front()[8].IsEqual(OrthancStone::ScenePoint2D(3, 4))); + ASSERT_TRUE(contours.front()[4].IsEqual(OrthancStone::ScenePoint2D(3, 4))); + + ASSERT_EQ(5u, contours.back().size()); + ASSERT_TRUE(contours.back()[0].IsEqual(OrthancStone::ScenePoint2D(2, 3))); + ASSERT_TRUE(contours.back()[1].IsEqual(OrthancStone::ScenePoint2D(3, 3))); + ASSERT_TRUE(contours.back()[2].IsEqual(OrthancStone::ScenePoint2D(3, 2))); + ASSERT_TRUE(contours.back()[3].IsEqual(OrthancStone::ScenePoint2D(2, 2))); + ASSERT_TRUE(contours.back()[4].IsEqual(OrthancStone::ScenePoint2D(2, 3))); } { @@ -938,17 +970,21 @@ std::list< std::vector > contours; OrthancStone::UnionOfRectangles::Apply(contours, rectangles); - ASSERT_EQ(1u, contours.size()); - ASSERT_EQ(9u, contours.front().size()); + ASSERT_EQ(2u, contours.size()); + + ASSERT_EQ(5u, contours.front().size()); ASSERT_TRUE(contours.front()[0].IsEqual(OrthancStone::ScenePoint2D(2, 3))); ASSERT_TRUE(contours.front()[1].IsEqual(OrthancStone::ScenePoint2D(3, 3))); ASSERT_TRUE(contours.front()[2].IsEqual(OrthancStone::ScenePoint2D(3, 2))); ASSERT_TRUE(contours.front()[3].IsEqual(OrthancStone::ScenePoint2D(2, 2))); - ASSERT_TRUE(contours.front()[4].IsEqual(OrthancStone::ScenePoint2D(2, 1))); - ASSERT_TRUE(contours.front()[5].IsEqual(OrthancStone::ScenePoint2D(1, 1))); - ASSERT_TRUE(contours.front()[6].IsEqual(OrthancStone::ScenePoint2D(1, 2))); - ASSERT_TRUE(contours.front()[7].IsEqual(OrthancStone::ScenePoint2D(2, 2))); - ASSERT_TRUE(contours.front()[8].IsEqual(OrthancStone::ScenePoint2D(2, 3))); + ASSERT_TRUE(contours.front()[4].IsEqual(OrthancStone::ScenePoint2D(2, 3))); + + ASSERT_EQ(5u, contours.back().size()); + ASSERT_TRUE(contours.back()[0].IsEqual(OrthancStone::ScenePoint2D(1, 2))); + ASSERT_TRUE(contours.back()[1].IsEqual(OrthancStone::ScenePoint2D(2, 2))); + ASSERT_TRUE(contours.back()[2].IsEqual(OrthancStone::ScenePoint2D(2, 1))); + ASSERT_TRUE(contours.back()[3].IsEqual(OrthancStone::ScenePoint2D(1, 1))); + ASSERT_TRUE(contours.back()[4].IsEqual(OrthancStone::ScenePoint2D(1, 2))); } {