Mercurial > hg > orthanc
diff OrthancFramework/Sources/Images/ImageProcessing.cpp @ 4875:5dae41084ab7
fix filling polygons
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 18 Jan 2022 15:04:04 +0100 |
parents | bee6da5155dc |
children | d8c8274d4e41 |
line wrap: on
line diff
--- a/OrthancFramework/Sources/Images/ImageProcessing.cpp Tue Jan 18 13:04:47 2022 +0100 +++ b/OrthancFramework/Sources/Images/ImageProcessing.cpp Tue Jan 18 15:04:04 2022 +0100 @@ -1983,8 +1983,8 @@ // For an index, return y-coordinate of next nonhorizontal line - static size_t GetPolygonNextY(const std::vector<ImageProcessing::ImagePoint>& points, - size_t k) + static int GetPolygonNextY(const std::vector<ImageProcessing::ImagePoint>& points, + size_t k) { // cf. "yNext()" in textbook size_t j = k; @@ -2005,8 +2005,8 @@ } - static size_t GetPolygonPreviousY(const std::vector<ImageProcessing::ImagePoint>& points, - size_t k) + static int GetPolygonPreviousY(const std::vector<ImageProcessing::ImagePoint>& points, + size_t k) { size_t j = k; @@ -2046,6 +2046,32 @@ return; } + bool onlyHorizontalSegments = true; + for (size_t i = 1; i < points.size(); i++) + { + if (points[0].GetY() != points[i].GetY()) + { + onlyHorizontalSegments = false; + break; + } + } + + if (onlyHorizontalSegments) + { + // Degenerate case: There are only horizontal lines. If this is + // the case, "GetPolygonPreviousY()" will be an infinite loop + int x1 = points[0].GetX(); + int x2 = points[0].GetX(); + for (size_t i = 1; i < points.size(); i++) + { + assert(points[i].GetY() == points[0].GetY()); + x1 = std::min(x1, points[i].GetX()); + x2 = std::max(x2, points[i].GetX()); + } + filler.Fill(points[0].GetY(), x1, x2); + return; + } + EdgeTable globalEdgeTable; // cf. "buildEdgeList()" in textbook @@ -2081,20 +2107,7 @@ v1 = v2; } - if (globalEdgeTable.empty()) - { - // Degenerate case: There were only horizontal lines - int x1 = points[0].GetX(); - int x2 = points[0].GetX(); - for (size_t i = 1; i < points.size(); i++) - { - assert(points[i].GetY() == points[0].GetY()); - x1 = std::min(x1, points[i].GetX()); - x2 = std::max(x2, points[i].GetX()); - } - filler.Fill(points[0].GetY(), x1, x2); - return; - } + assert(!globalEdgeTable.empty()); std::vector<PolygonEdge> activeEdges; @@ -2147,11 +2160,23 @@ std::sort(activeEdges.begin(), activeEdges.end()); // cf. "fillScan()" in textbook - for (size_t k = 0; k + 1 < activeEdges.size(); k += 2) + for (size_t k = 0; k + 1 < activeEdges.size(); ) { int a = activeEdges[k].GetExitX(); int b = activeEdges[k + 1].GetEnterX(); - filler.Fill(y, std::min(a, b), std::max(a, b)); + + // Fix wrt. the textbook: merge overlapping segments + k += 2; + while (k + 1 < activeEdges.size() && + activeEdges[k].GetExitX() == b) + { + assert(a <= b); + b = activeEdges[k + 1].GetEnterX(); + k += 2; + } + + assert(a <= b); + filler.Fill(y, a, b); } // cf. "updateActiveList()" in textbook