Mercurial > hg > orthanc-stone
annotate Framework/Toolbox/SlicesSorter.cpp @ 525:2549363fadc3 am-touch-events
Close branch am-touch-events.
author | Alain Mazy <am@osimis.io> |
---|---|
date | Tue, 12 Mar 2019 17:29:12 +0000 |
parents | b70e9be013e4 |
children | 6af3099ed8da |
rev | line source |
---|---|
73 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
439 | 5 * Copyright (C) 2017-2019 Osimis S.A., Belgium |
73 | 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 | |
159
0a73d76333db
populating LinearAlgebra
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
135
diff
changeset
|
24 #include "GeometryToolbox.h" |
0a73d76333db
populating LinearAlgebra
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
135
diff
changeset
|
25 |
212
5412adf19980
resort to OrthancFramework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
201
diff
changeset
|
26 #include <Core/OrthancException.h> |
73 | 27 |
28 namespace OrthancStone | |
29 { | |
30 class SlicesSorter::SliceWithDepth : public boost::noncopyable | |
31 { | |
32 private: | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
33 std::auto_ptr<Slice> slice_; |
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
34 double depth_; |
73 | 35 |
36 public: | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
37 SliceWithDepth(Slice* slice) : |
73 | 38 slice_(slice), |
39 depth_(0) | |
40 { | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
41 if (slice == NULL) |
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
42 { |
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
43 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); |
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
44 } |
73 | 45 } |
46 | |
47 void SetNormal(const Vector& normal) | |
48 { | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
49 assert(slice_.get() != NULL); |
73 | 50 depth_ = boost::numeric::ublas::inner_prod |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
51 (slice_->GetGeometry().GetOrigin(), normal); |
73 | 52 } |
53 | |
54 double GetDepth() const | |
55 { | |
56 return depth_; | |
57 } | |
58 | |
59 const Slice& GetSlice() const | |
60 { | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
61 assert(slice_.get() != NULL); |
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
62 return *slice_; |
73 | 63 } |
64 }; | |
65 | |
66 | |
67 struct SlicesSorter::Comparator | |
68 { | |
69 bool operator() (const SliceWithDepth* const& a, | |
70 const SliceWithDepth* const& b) const | |
71 { | |
72 return a->GetDepth() < b->GetDepth(); | |
73 } | |
74 }; | |
75 | |
76 | |
77 SlicesSorter::~SlicesSorter() | |
78 { | |
79 for (size_t i = 0; i < slices_.size(); i++) | |
80 { | |
81 assert(slices_[i] != NULL); | |
82 delete slices_[i]; | |
83 } | |
84 } | |
85 | |
86 | |
119
ba83e38cf3ff
rendering of rt-dose
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
113
diff
changeset
|
87 void SlicesSorter::AddSlice(Slice* slice) |
73 | 88 { |
89 slices_.push_back(new SliceWithDepth(slice)); | |
90 } | |
91 | |
92 | |
93 const Slice& SlicesSorter::GetSlice(size_t i) const | |
94 { | |
95 if (i >= slices_.size()) | |
96 { | |
97 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
98 } | |
99 | |
100 assert(slices_[i] != NULL); | |
101 return slices_[i]->GetSlice(); | |
102 } | |
103 | |
104 | |
105 void SlicesSorter::SetNormal(const Vector& normal) | |
106 { | |
107 for (size_t i = 0; i < slices_.size(); i++) | |
108 { | |
109 slices_[i]->SetNormal(normal); | |
110 } | |
111 | |
112 hasNormal_ = true; | |
113 } | |
114 | |
115 | |
116 void SlicesSorter::Sort() | |
117 { | |
118 if (!hasNormal_) | |
119 { | |
120 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
121 } | |
122 | |
123 Comparator comparator; | |
124 std::sort(slices_.begin(), slices_.end(), comparator); | |
125 } | |
126 | |
127 | |
128 void SlicesSorter::FilterNormal(const Vector& normal) | |
129 { | |
130 size_t pos = 0; | |
131 | |
132 for (size_t i = 0; i < slices_.size(); i++) | |
133 { | |
134 if (GeometryToolbox::IsParallel(normal, slices_[i]->GetSlice().GetGeometry().GetNormal())) | |
135 { | |
136 // This slice is compatible with the selected normal | |
137 slices_[pos] = slices_[i]; | |
138 pos += 1; | |
139 } | |
140 else | |
141 { | |
142 delete slices_[i]; | |
143 slices_[i] = NULL; | |
144 } | |
145 } | |
146 | |
147 slices_.resize(pos); | |
148 } | |
149 | |
150 | |
151 bool SlicesSorter::SelectNormal(Vector& normal) const | |
152 { | |
153 std::vector<Vector> normalCandidates; | |
154 std::vector<unsigned int> normalCount; | |
155 | |
156 bool found = false; | |
157 | |
158 for (size_t i = 0; !found && i < GetSliceCount(); i++) | |
159 { | |
160 const Vector& normal = GetSlice(i).GetGeometry().GetNormal(); | |
161 | |
162 bool add = true; | |
163 for (size_t j = 0; add && j < normalCandidates.size(); j++) // (*) | |
164 { | |
165 if (GeometryToolbox::IsParallel(normal, normalCandidates[j])) | |
166 { | |
167 normalCount[j] += 1; | |
168 add = false; | |
169 } | |
170 } | |
171 | |
172 if (add) | |
173 { | |
174 if (normalCount.size() > 2) | |
175 { | |
176 // To get linear-time complexity in (*). This heuristics | |
177 // allows the series to have one single frame that is | |
178 // not parallel to the others (such a frame could be a | |
179 // generated preview) | |
180 found = false; | |
181 } | |
182 else | |
183 { | |
184 normalCandidates.push_back(normal); | |
185 normalCount.push_back(1); | |
186 } | |
187 } | |
188 } | |
189 | |
190 for (size_t i = 0; !found && i < normalCandidates.size(); i++) | |
191 { | |
192 unsigned int count = normalCount[i]; | |
193 if (count == GetSliceCount() || | |
194 count + 1 == GetSliceCount()) | |
195 { | |
196 normal = normalCandidates[i]; | |
197 found = true; | |
198 } | |
199 } | |
200 | |
201 return found; | |
202 } | |
77 | 203 |
204 | |
205 bool SlicesSorter::LookupSlice(size_t& index, | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
77
diff
changeset
|
206 const CoordinateSystem3D& slice) const |
77 | 207 { |
208 // TODO Turn this linear-time lookup into a log-time lookup, | |
209 // keeping track of whether the slices are sorted along the normal | |
210 | |
211 for (size_t i = 0; i < slices_.size(); i++) | |
212 { | |
213 if (slices_[i]->GetSlice().ContainsPlane(slice)) | |
214 { | |
215 index = i; | |
216 return true; | |
217 } | |
218 } | |
219 | |
220 return false; | |
221 } | |
73 | 222 } |