comparison OrthancStone/Sources/Toolbox/BucketAccumulator2D.cpp @ 1891:3716d72161d2

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 19 Jan 2022 12:32:15 +0100
parents
children cdf91ad891a5
comparison
equal deleted inserted replaced
1890:6ce81914f7e4 1891:3716d72161d2
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 "BucketAccumulator2D.h"
25
26 #include "LinearAlgebra.h"
27
28 #include <OrthancException.h>
29
30
31 namespace OrthancStone
32 {
33 size_t BucketAccumulator2D::FindBestInternal() const
34 {
35 size_t best = 0;
36
37 for (size_t i = 0; i < buckets_.size(); i++)
38 {
39 if (buckets_[i].count_ > buckets_[best].count_)
40 {
41 best = i;
42 }
43 }
44
45 return best;
46 }
47
48
49 size_t BucketAccumulator2D::EncodeIndex(size_t x,
50 size_t y) const
51 {
52 if (x >= mapperX_.GetSize() ||
53 y >= mapperX_.GetSize())
54 {
55 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
56 }
57 else
58 {
59 return x + y * mapperX_.GetSize();
60 }
61 }
62
63
64 void BucketAccumulator2D::DecodeIndex(size_t& x,
65 size_t& y,
66 size_t index) const
67 {
68 assert(buckets_.size() == mapperX_.GetSize() * mapperY_.GetSize());
69
70 if (index >= buckets_.size())
71 {
72 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
73 }
74 else
75 {
76 x = index % mapperX_.GetSize();
77 y = index / mapperX_.GetSize();
78 }
79 }
80
81
82 BucketAccumulator2D::BucketAccumulator2D(double minValueX,
83 double maxValueX,
84 size_t countBucketsX,
85 double minValueY,
86 double maxValueY,
87 size_t countBucketsY,
88 bool storeValues) :
89 mapperX_(minValueX, maxValueX, countBucketsX),
90 mapperY_(minValueY, maxValueY, countBucketsY),
91 buckets_(countBucketsX * countBucketsY),
92 storeValues_(storeValues)
93 {
94 }
95
96
97 void BucketAccumulator2D::GetSize(size_t& x,
98 size_t& y) const
99 {
100 x = mapperX_.GetSize();
101 y = mapperY_.GetSize();
102 }
103
104
105 size_t BucketAccumulator2D::GetBucketContentSize(size_t x,
106 size_t y) const
107 {
108 return buckets_[EncodeIndex(x, y)].count_;
109 }
110
111
112 void BucketAccumulator2D::GetBucketIndex(size_t& bucketX,
113 size_t& bucketY,
114 double valueX,
115 double valueY) const
116 {
117 bucketX = mapperX_.GetBucketIndex(valueX);
118 bucketY = mapperY_.GetBucketIndex(valueY);
119 }
120
121
122 void BucketAccumulator2D::AddValue(double valueX,
123 double valueY)
124 {
125 size_t x = mapperX_.GetBucketIndex(valueX);
126 size_t y = mapperY_.GetBucketIndex(valueY);
127
128 Bucket& bucket = buckets_[EncodeIndex(x, y)];
129
130 bucket.count_++;
131
132 if (storeValues_)
133 {
134 bucket.valuesX_.push_back(valueX);
135 bucket.valuesY_.push_back(valueY);
136 }
137 }
138
139
140 void BucketAccumulator2D::ComputeBestCenter(double& x,
141 double& y) const
142 {
143 size_t bucketX, bucketY;
144 FindBestBucket(bucketX, bucketY);
145 x = mapperX_.GetBucketCenter(bucketX);
146 y = mapperY_.GetBucketCenter(bucketY);
147 }
148
149
150 void BucketAccumulator2D::ComputeBestMedian(double& x,
151 double& y) const
152 {
153 if (!storeValues_)
154 {
155 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
156 }
157
158 const std::list<double>& valuesX = buckets_[FindBestInternal()].valuesX_;
159 const std::list<double>& valuesY = buckets_[FindBestInternal()].valuesY_;
160
161 std::vector<double> v;
162 v.reserve(valuesX.size());
163 for (std::list<double>::const_iterator it = valuesX.begin(); it != valuesX.end(); ++it)
164 {
165 v.push_back(*it);
166 }
167
168 x = LinearAlgebra::ComputeMedian(v);
169
170 v.clear();
171 v.reserve(valuesY.size());
172 for (std::list<double>::const_iterator it = valuesY.begin(); it != valuesY.end(); ++it)
173 {
174 v.push_back(*it);
175 }
176
177 y = LinearAlgebra::ComputeMedian(v);
178 }
179 }