comparison OrthancServer/SliceOrdering.cpp @ 2804:d88970f1ffbf

fix ordering of non-parallel slices + /tools/reconstruct
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 29 Aug 2018 13:24:28 +0200
parents 878b59270859
children bbfd95a0c429
comparison
equal deleted inserted replaced
2803:579acc5e5412 2804:d88970f1ffbf
93 return TokenizeVector(result, value->GetContent(), expectedSize); 93 return TokenizeVector(result, value->GetContent(), expectedSize);
94 } 94 }
95 } 95 }
96 96
97 97
98 static bool IsCloseToZero(double x)
99 {
100 return fabs(x) < 10.0 * std::numeric_limits<float>::epsilon();
101 }
102
103
104 bool SliceOrdering::ComputeNormal(Vector& normal,
105 const DicomMap& dicom)
106 {
107 std::vector<float> cosines;
108
109 if (TokenizeVector(cosines, dicom, DICOM_TAG_IMAGE_ORIENTATION_PATIENT, 6))
110 {
111 assert(cosines.size() == 6);
112 normal[0] = cosines[1] * cosines[5] - cosines[2] * cosines[4];
113 normal[1] = cosines[2] * cosines[3] - cosines[0] * cosines[5];
114 normal[2] = cosines[0] * cosines[4] - cosines[1] * cosines[3];
115 return true;
116 }
117 else
118 {
119 return false;
120 }
121 }
122
123
124 bool SliceOrdering::IsParallelOrOpposite(const Vector& u,
125 const Vector& v)
126 {
127 // Check out "GeometryToolbox::IsParallelOrOpposite()" in Stone of
128 // Orthanc for explanations
129 const double u1 = u[0];
130 const double u2 = u[1];
131 const double u3 = u[2];
132 const double normU = sqrt(u1 * u1 + u2 * u2 + u3 * u3);
133
134 const double v1 = v[0];
135 const double v2 = v[1];
136 const double v3 = v[2];
137 const double normV = sqrt(v1 * v1 + v2 * v2 + v3 * v3);
138
139 if (IsCloseToZero(normU * normV))
140 {
141 return false;
142 }
143 else
144 {
145 const double cosAngle = (u1 * v1 + u2 * v2 + u3 * v3) / (normU * normV);
146
147 return (IsCloseToZero(cosAngle - 1.0) || // Close to +1: Parallel, non-opposite
148 IsCloseToZero(fabs(cosAngle) - 1.0)); // Close to -1: Parallel, opposite
149 }
150 }
151
152
98 struct SliceOrdering::Instance : public boost::noncopyable 153 struct SliceOrdering::Instance : public boost::noncopyable
99 { 154 {
100 private: 155 private:
101 std::string instanceId_; 156 std::string instanceId_;
102 bool hasPosition_; 157 bool hasPosition_;
103 Vector position_; 158 Vector position_;
159 bool hasNormal_;
160 Vector normal_;
104 bool hasIndexInSeries_; 161 bool hasIndexInSeries_;
105 size_t indexInSeries_; 162 size_t indexInSeries_;
106 unsigned int framesCount_; 163 unsigned int framesCount_;
107 164
108 public: 165 public:
139 position_[0] = tmp[0]; 196 position_[0] = tmp[0];
140 position_[1] = tmp[1]; 197 position_[1] = tmp[1];
141 position_[2] = tmp[2]; 198 position_[2] = tmp[2];
142 } 199 }
143 200
201 hasNormal_ = ComputeNormal(normal_, instance);
202
144 std::string s; 203 std::string s;
145 hasIndexInSeries_ = false; 204 hasIndexInSeries_ = false;
146 205
147 try 206 try
148 { 207 {
188 247
189 unsigned int GetFramesCount() const 248 unsigned int GetFramesCount() const
190 { 249 {
191 return framesCount_; 250 return framesCount_;
192 } 251 }
252
253 bool HasNormal() const
254 {
255 return hasNormal_;
256 }
257
258 const Vector& GetNormal() const
259 {
260 assert(hasNormal_);
261 return normal_;
262 }
193 }; 263 };
194 264
195 265
196 class SliceOrdering::PositionComparator 266 class SliceOrdering::PositionComparator
197 { 267 {
224 if (!index_.GetMainDicomTags(series, seriesId_, ResourceType_Series, ResourceType_Series)) 294 if (!index_.GetMainDicomTags(series, seriesId_, ResourceType_Series, ResourceType_Series))
225 { 295 {
226 throw OrthancException(ErrorCode_UnknownResource); 296 throw OrthancException(ErrorCode_UnknownResource);
227 } 297 }
228 298
229 std::vector<float> cosines; 299 hasNormal_ = ComputeNormal(normal_, series);
230 hasNormal_ = TokenizeVector(cosines, series, DICOM_TAG_IMAGE_ORIENTATION_PATIENT, 6);
231
232 if (hasNormal_)
233 {
234 normal_[0] = cosines[1] * cosines[5] - cosines[2] * cosines[4];
235 normal_[1] = cosines[2] * cosines[3] - cosines[0] * cosines[5];
236 normal_[2] = cosines[0] * cosines[4] - cosines[1] * cosines[3];
237 }
238 } 300 }
239 301
240 302
241 void SliceOrdering::CreateInstances() 303 void SliceOrdering::CreateInstances()
242 { 304 {
266 } 328 }
267 329
268 for (size_t i = 0; i < instances_.size(); i++) 330 for (size_t i = 0; i < instances_.size(); i++)
269 { 331 {
270 assert(instances_[i] != NULL); 332 assert(instances_[i] != NULL);
271 if (!instances_[i]->HasPosition()) 333
334 if (!instances_[i]->HasPosition() ||
335 (instances_[i]->HasNormal() &&
336 !IsParallelOrOpposite(instances_[i]->GetNormal(), normal_)))
272 { 337 {
273 return false; 338 return false;
274 } 339 }
275 } 340 }
276 341