# HG changeset patch # User Sebastien Jodogne # Date 1654197744 -7200 # Node ID 3c68cdfbdcabdc7a6db532dc471164b3148f5872 # Parent 98952be6fb97f4d6e4dca02951fe5dccc0924ef1 rendering plugin: deal with special case of holes in structs diff -r 98952be6fb97 -r 3c68cdfbdcab RenderingPlugin/Sources/Plugin.cpp --- a/RenderingPlugin/Sources/Plugin.cpp Thu Jun 02 12:23:45 2022 +0200 +++ b/RenderingPlugin/Sources/Plugin.cpp Thu Jun 02 21:22:24 2022 +0200 @@ -715,7 +715,7 @@ Orthanc::ImageProcessing::Set(image_, 0); } - const Orthanc::ImageAccessor& GetImage() const + Orthanc::ImageAccessor& GetImage() { return image_; } @@ -737,11 +737,65 @@ for (int i = x1; i <= x2; i++, p++) { *p = (*p ^ 0xff); - } + } } } }; + + class HorizontalSegment + { + private: + int y_; + int x1_; + int x2_; + + public: + HorizontalSegment(int y, + int x1, + int x2) : + y_(y), + x1_(std::min(x1, x2)), + x2_(std::max(x1, x2)) + { + } + + int GetY() const + { + return y_; + } + + int GetX1() const + { + return x1_; + } + + int GetX2() const + { + return x2_; + } + + void Fill(Orthanc::ImageAccessor& image) const + { + assert(x1_ <= x2_); + + if (y_ >= 0 && + y_ < static_cast(image.GetHeight())) + { + int a = std::max(x1_, 0); + int b = std::min(x2_, static_cast(image.GetWidth()) - 1); + + uint8_t* p = reinterpret_cast(image.GetRow(y_)) + a; + + for (int i = a; i <= b; i++, p++) + { + *p = 0xff; + } + } + } + }; + + DataAugmentationParameters dataAugmentation; std::vector structureNames; std::string instanceId; @@ -815,6 +869,8 @@ XorFiller filler(parameters->GetWidth(), parameters->GetHeight()); OrthancStone::AffineTransform2D transform = dataAugmentation.ComputeTransform(parameters->GetWidth(), parameters->GetHeight()); + std::list horizontalSegments; + for (std::list< std::vector >::const_iterator it = polygons.begin(); it != polygons.end(); ++it) { @@ -833,12 +889,35 @@ transform.Apply(x, y); - points.push_back(Orthanc::ImageProcessing::ImagePoint(x, y)); + points.push_back(Orthanc::ImageProcessing::ImagePoint(std::floor(x), std::floor(y))); } + + Orthanc::ImageProcessing::FillPolygon(filler, points); - Orthanc::ImageProcessing::FillPolygon(filler, points); + for (size_t i = 0; i < points.size(); i++) + { + size_t next = (i + 1) % points.size(); + if (points[i].GetY() == points[next].GetY()) + { + horizontalSegments.push_back(HorizontalSegment(points[i].GetY(), points[i].GetX(), points[next].GetX())); + } + } } + /** + * We repeat the filling of the horizontal segments. This is + * important to deal with horizontal edges that are seen in one + * direction, then in the reverse direction within the same polygon, + * which can typically be seen in RT-STRUCT with holes. If this step + * is not done, only the starting point and the ending point of the + * segments are drawn. + **/ + for (std::list::const_iterator it = horizontalSegments.begin(); + it != horizontalSegments.end(); ++it) + { + it->Fill(filler.GetImage()); + } + AnswerNumpyImage(output, filler.GetImage(), compress); }