comparison OrthancStone/Sources/Toolbox/Internals/RectanglesIntegerProjection.cpp @ 1874:08f2476e8f5e

added classes OrientedIntegerLine2D and RectanglesIntegerProjection
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 11 Jan 2022 18:58:37 +0100
parents
children e318b524ad3f
comparison
equal deleted inserted replaced
1873:e0966648ebd0 1874:08f2476e8f5e
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2022 Osimis S.A., Belgium
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
7 *
8 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation, either version 3 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 **/
22
23
24 #include "RectanglesIntegerProjection.h"
25
26 #include <OrthancException.h>
27
28 #include <algorithm>
29 #include <cassert>
30
31
32 namespace OrthancStone
33 {
34 namespace Internals
35 {
36 class RectanglesIntegerProjection::Endpoint
37 {
38 private:
39 size_t intervalIndex_;
40 double value_;
41 bool isLow_;
42
43 public:
44 Endpoint(size_t intervalIndex,
45 double value,
46 bool isLow) :
47 intervalIndex_(intervalIndex),
48 value_(value),
49 isLow_(isLow)
50 {
51 }
52
53 bool operator< (const Endpoint& other) const
54 {
55 if (value_ < other.value_)
56 {
57 return true;
58 }
59 else if (value_ == other.value_)
60 {
61 return isLow_;
62 }
63 else
64 {
65 return false;
66 }
67 }
68
69 size_t GetIntervalIndex() const
70 {
71 return intervalIndex_;
72 }
73
74 double GetValue() const
75 {
76 return value_;
77 }
78
79 bool IsLow() const
80 {
81 return isLow_;
82 }
83 };
84
85
86 RectanglesIntegerProjection::RectanglesIntegerProjection(const std::list<Extent2D>& rectangles,
87 bool isHorizontal)
88 {
89 std::vector<Endpoint> endpoints;
90 endpoints.reserve(2 * rectangles.size());
91
92 size_t count = 0;
93 for (std::list<Extent2D>::const_iterator it = rectangles.begin(); it != rectangles.end(); ++it)
94 {
95 if (!it->IsEmpty())
96 {
97 if (isHorizontal)
98 {
99 assert(it->GetX1() < it->GetX2());
100 endpoints.push_back(Endpoint(count, it->GetX1(), true));
101 endpoints.push_back(Endpoint(count, it->GetX2(), false));
102 }
103 else
104 {
105 assert(it->GetY1() < it->GetY2());
106 endpoints.push_back(Endpoint(count, it->GetY1(), true));
107 endpoints.push_back(Endpoint(count, it->GetY2(), false));
108 }
109
110 assert(endpoints[endpoints.size() - 2] < endpoints[endpoints.size() - 1]);
111
112 count++;
113 }
114 }
115
116 std::sort(endpoints.begin(), endpoints.end());
117
118 intervalsLow_.resize(count);
119 intervalsHigh_.resize(count);
120 endpointsToDouble_.reserve(count);
121
122 for (size_t i = 0; i < endpoints.size(); i++)
123 {
124 if (endpointsToDouble_.empty() ||
125 endpointsToDouble_.back() < endpoints[i].GetValue())
126 {
127 endpointsToDouble_.push_back(endpoints[i].GetValue());
128 }
129
130 size_t intervalIndex = endpoints[i].GetIntervalIndex();
131
132 if (endpoints[i].IsLow())
133 {
134 intervalsLow_[intervalIndex] = endpointsToDouble_.size() - 1;
135 }
136 else
137 {
138 intervalsHigh_[intervalIndex] = endpointsToDouble_.size() - 1;
139 }
140 }
141
142 for (size_t i = 0; i < intervalsLow_.size(); i++)
143 {
144 assert(intervalsLow_[i] < intervalsHigh_[i]);
145 }
146 }
147
148
149 double RectanglesIntegerProjection::GetEndpointCoordinate(size_t index) const
150 {
151 if (index >= endpointsToDouble_.size())
152 {
153 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
154 }
155 else
156 {
157 return endpointsToDouble_[index];
158 }
159 }
160
161
162 size_t RectanglesIntegerProjection::GetProjectedRectanglesCount() const
163 {
164 assert(intervalsLow_.size() == intervalsHigh_.size());
165 return intervalsLow_.size();
166 }
167
168
169 size_t RectanglesIntegerProjection::GetProjectedRectangleLow(size_t index) const
170 {
171 if (index >= GetProjectedRectanglesCount())
172 {
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
174 }
175 else
176 {
177 return intervalsLow_[index];
178 }
179 }
180
181
182 size_t RectanglesIntegerProjection::GetProjectedRectangleHigh(size_t index) const
183 {
184 if (index >= GetProjectedRectanglesCount())
185 {
186 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
187 }
188 else
189 {
190 return intervalsHigh_[index];
191 }
192 }
193 }
194 }