comparison Framework/Toolbox/SlicesSorter.cpp @ 73:ffa6dded91bd wasm

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 24 May 2017 11:59:24 +0200
parents
children f5f54ed8d307
comparison
equal deleted inserted replaced
72:c1cc3bdba18c 73:ffa6dded91bd
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 Osimis, Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "SlicesSorter.h"
23
24 #include "../../Resources/Orthanc/Core/OrthancException.h"
25
26 namespace OrthancStone
27 {
28 class SlicesSorter::SliceWithDepth : public boost::noncopyable
29 {
30 private:
31 Slice slice_;
32 double depth_;
33
34 public:
35 SliceWithDepth(const Slice& slice) :
36 slice_(slice),
37 depth_(0)
38 {
39 }
40
41 void SetNormal(const Vector& normal)
42 {
43 depth_ = boost::numeric::ublas::inner_prod
44 (slice_.GetGeometry().GetOrigin(), normal);
45 }
46
47 double GetDepth() const
48 {
49 return depth_;
50 }
51
52 const Slice& GetSlice() const
53 {
54 return slice_;
55 }
56 };
57
58
59 struct SlicesSorter::Comparator
60 {
61 bool operator() (const SliceWithDepth* const& a,
62 const SliceWithDepth* const& b) const
63 {
64 return a->GetDepth() < b->GetDepth();
65 }
66 };
67
68
69 SlicesSorter::~SlicesSorter()
70 {
71 for (size_t i = 0; i < slices_.size(); i++)
72 {
73 assert(slices_[i] != NULL);
74 delete slices_[i];
75 }
76 }
77
78
79 void SlicesSorter::AddSlice(const Slice& slice)
80 {
81 slices_.push_back(new SliceWithDepth(slice));
82 }
83
84
85 const Slice& SlicesSorter::GetSlice(size_t i) const
86 {
87 if (i >= slices_.size())
88 {
89 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
90 }
91
92 assert(slices_[i] != NULL);
93 return slices_[i]->GetSlice();
94 }
95
96
97 void SlicesSorter::SetNormal(const Vector& normal)
98 {
99 for (size_t i = 0; i < slices_.size(); i++)
100 {
101 slices_[i]->SetNormal(normal);
102 }
103
104 hasNormal_ = true;
105 }
106
107
108 void SlicesSorter::Sort()
109 {
110 if (!hasNormal_)
111 {
112 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
113 }
114
115 Comparator comparator;
116 std::sort(slices_.begin(), slices_.end(), comparator);
117 }
118
119
120 void SlicesSorter::FilterNormal(const Vector& normal)
121 {
122 size_t pos = 0;
123
124 for (size_t i = 0; i < slices_.size(); i++)
125 {
126 if (GeometryToolbox::IsParallel(normal, slices_[i]->GetSlice().GetGeometry().GetNormal()))
127 {
128 // This slice is compatible with the selected normal
129 slices_[pos] = slices_[i];
130 pos += 1;
131 }
132 else
133 {
134 delete slices_[i];
135 slices_[i] = NULL;
136 }
137 }
138
139 slices_.resize(pos);
140 }
141
142
143 bool SlicesSorter::SelectNormal(Vector& normal) const
144 {
145 std::vector<Vector> normalCandidates;
146 std::vector<unsigned int> normalCount;
147
148 bool found = false;
149
150 for (size_t i = 0; !found && i < GetSliceCount(); i++)
151 {
152 const Vector& normal = GetSlice(i).GetGeometry().GetNormal();
153
154 bool add = true;
155 for (size_t j = 0; add && j < normalCandidates.size(); j++) // (*)
156 {
157 if (GeometryToolbox::IsParallel(normal, normalCandidates[j]))
158 {
159 normalCount[j] += 1;
160 add = false;
161 }
162 }
163
164 if (add)
165 {
166 if (normalCount.size() > 2)
167 {
168 // To get linear-time complexity in (*). This heuristics
169 // allows the series to have one single frame that is
170 // not parallel to the others (such a frame could be a
171 // generated preview)
172 found = false;
173 }
174 else
175 {
176 normalCandidates.push_back(normal);
177 normalCount.push_back(1);
178 }
179 }
180 }
181
182 for (size_t i = 0; !found && i < normalCandidates.size(); i++)
183 {
184 unsigned int count = normalCount[i];
185 if (count == GetSliceCount() ||
186 count + 1 == GetSliceCount())
187 {
188 normal = normalCandidates[i];
189 found = true;
190 }
191 }
192
193 return found;
194 }
195 }