Mercurial > hg > orthanc-stone
view OrthancStone/Sources/Toolbox/Internals/RectanglesIntegerProjection.cpp @ 1905:e318b524ad3f
use UnionOfRectangles algorithm to render RT-STRUCT
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 31 Jan 2022 18:50:35 +0100 |
parents | 08f2476e8f5e |
children | 07964689cb0b |
line wrap: on
line source
/** * Stone of Orthanc * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2022 Osimis S.A., Belgium * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/>. **/ #include "RectanglesIntegerProjection.h" #include <OrthancException.h> #include <algorithm> #include <cassert> namespace OrthancStone { namespace Internals { class RectanglesIntegerProjection::Endpoint { private: size_t intervalIndex_; double value_; bool isLow_; public: Endpoint(size_t intervalIndex, double value, bool isLow) : intervalIndex_(intervalIndex), value_(value), isLow_(isLow) { } bool operator< (const Endpoint& other) const { if (value_ < other.value_) { return true; } else if (value_ == other.value_) { return static_cast<int>(isLow_) < static_cast<int>(other.isLow_); } else { return false; } } size_t GetIntervalIndex() const { return intervalIndex_; } double GetValue() const { return value_; } bool IsLow() const { return isLow_; } }; RectanglesIntegerProjection::RectanglesIntegerProjection(const std::list<Extent2D>& rectangles, bool isHorizontal) { std::vector<Endpoint> endpoints; endpoints.reserve(2 * rectangles.size()); size_t count = 0; for (std::list<Extent2D>::const_iterator it = rectangles.begin(); it != rectangles.end(); ++it) { if (!it->IsEmpty()) { if (isHorizontal) { assert(it->GetX1() < it->GetX2()); endpoints.push_back(Endpoint(count, it->GetX1(), true)); endpoints.push_back(Endpoint(count, it->GetX2(), false)); } else { assert(it->GetY1() < it->GetY2()); endpoints.push_back(Endpoint(count, it->GetY1(), true)); endpoints.push_back(Endpoint(count, it->GetY2(), false)); } assert(endpoints[endpoints.size() - 2] < endpoints[endpoints.size() - 1]); count++; } } std::sort(endpoints.begin(), endpoints.end()); intervalsLow_.resize(count); intervalsHigh_.resize(count); endpointsToDouble_.reserve(count); for (size_t i = 0; i < endpoints.size(); i++) { if (endpointsToDouble_.empty() || endpointsToDouble_.back() < endpoints[i].GetValue()) { endpointsToDouble_.push_back(endpoints[i].GetValue()); } size_t intervalIndex = endpoints[i].GetIntervalIndex(); if (endpoints[i].IsLow()) { intervalsLow_[intervalIndex] = endpointsToDouble_.size() - 1; } else { intervalsHigh_[intervalIndex] = endpointsToDouble_.size() - 1; } } for (size_t i = 0; i < intervalsLow_.size(); i++) { assert(intervalsLow_[i] < intervalsHigh_[i]); } } double RectanglesIntegerProjection::GetEndpointCoordinate(size_t index) const { if (index >= endpointsToDouble_.size()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { return endpointsToDouble_[index]; } } size_t RectanglesIntegerProjection::GetProjectedRectanglesCount() const { assert(intervalsLow_.size() == intervalsHigh_.size()); return intervalsLow_.size(); } size_t RectanglesIntegerProjection::GetProjectedRectangleLow(size_t index) const { if (index >= GetProjectedRectanglesCount()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { return intervalsLow_[index]; } } size_t RectanglesIntegerProjection::GetProjectedRectangleHigh(size_t index) const { if (index >= GetProjectedRectanglesCount()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { return intervalsHigh_[index]; } } } }