Mercurial > hg > orthanc-stone
comparison Framework/dev.h @ 647:6af3099ed8da
uncoupling OrthancStone::SlicesSorter from OrthancStone::Slice
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 13 May 2019 17:03:46 +0200 |
parents | 573e35378999 |
children | 7719eb852dd5 |
comparison
equal
deleted
inserted
replaced
646:b4fe9642e83b | 647:6af3099ed8da |
---|---|
108 | 108 |
109 void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) | 109 void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) |
110 { | 110 { |
111 assert(&message.GetOrigin() == &loader_); | 111 assert(&message.GetOrigin() == &loader_); |
112 | 112 |
113 if (loader_.GetSliceCount() == 0) | 113 if (loader_.GetSlicesCount() == 0) |
114 { | 114 { |
115 LOG(ERROR) << "Empty volume image"; | 115 LOG(ERROR) << "Empty volume image"; |
116 BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); | 116 BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); |
117 return; | 117 return; |
118 } | 118 } |
119 | 119 |
120 for (size_t i = 1; i < loader_.GetSliceCount(); i++) | 120 for (size_t i = 1; i < loader_.GetSlicesCount(); i++) |
121 { | 121 { |
122 if (!IsCompatible(loader_.GetSlice(0), loader_.GetSlice(i))) | 122 if (!IsCompatible(loader_.GetSlice(0), loader_.GetSlice(i))) |
123 { | 123 { |
124 BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); | 124 BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); |
125 return; | 125 return; |
126 } | 126 } |
127 } | 127 } |
128 | 128 |
129 double spacingZ; | 129 double spacingZ; |
130 | 130 |
131 if (loader_.GetSliceCount() > 1) | 131 if (loader_.GetSlicesCount() > 1) |
132 { | 132 { |
133 spacingZ = GetDistance(loader_.GetSlice(0), loader_.GetSlice(1)); | 133 spacingZ = GetDistance(loader_.GetSlice(0), loader_.GetSlice(1)); |
134 } | 134 } |
135 else | 135 else |
136 { | 136 { |
137 // This is a volume with one single slice: Choose a dummy | 137 // This is a volume with one single slice: Choose a dummy |
138 // z-dimension for voxels | 138 // z-dimension for voxels |
139 spacingZ = 1; | 139 spacingZ = 1; |
140 } | 140 } |
141 | 141 |
142 for (size_t i = 1; i < loader_.GetSliceCount(); i++) | 142 for (size_t i = 1; i < loader_.GetSlicesCount(); i++) |
143 { | 143 { |
144 if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)), | 144 if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)), |
145 0.001 /* this is expressed in mm */)) | 145 0.001 /* this is expressed in mm */)) |
146 { | 146 { |
147 LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; | 147 LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; |
152 | 152 |
153 unsigned int width = loader_.GetSlice(0).GetWidth(); | 153 unsigned int width = loader_.GetSlice(0).GetWidth(); |
154 unsigned int height = loader_.GetSlice(0).GetHeight(); | 154 unsigned int height = loader_.GetSlice(0).GetHeight(); |
155 Orthanc::PixelFormat format = loader_.GetSlice(0).GetConverter().GetExpectedPixelFormat(); | 155 Orthanc::PixelFormat format = loader_.GetSlice(0).GetConverter().GetExpectedPixelFormat(); |
156 LOG(INFO) << "Creating a volume image of size " << width << "x" << height | 156 LOG(INFO) << "Creating a volume image of size " << width << "x" << height |
157 << "x" << loader_.GetSliceCount() << " in " << Orthanc::EnumerationToString(format); | 157 << "x" << loader_.GetSlicesCount() << " in " << Orthanc::EnumerationToString(format); |
158 | 158 |
159 image_.reset(new ImageBuffer3D(format, width, height, static_cast<unsigned int>(loader_.GetSliceCount()), computeRange_)); | 159 image_.reset(new ImageBuffer3D(format, width, height, static_cast<unsigned int>(loader_.GetSlicesCount()), computeRange_)); |
160 image_->SetAxialGeometry(loader_.GetSlice(0).GetGeometry()); | 160 image_->SetAxialGeometry(loader_.GetSlice(0).GetGeometry()); |
161 image_->SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(), | 161 image_->SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(), |
162 loader_.GetSlice(0).GetPixelSpacingY(), spacingZ); | 162 loader_.GetSlice(0).GetPixelSpacingY(), spacingZ); |
163 image_->Clear(); | 163 image_->Clear(); |
164 | 164 |
165 downloadStack_.reset(new DownloadStack(static_cast<unsigned int>(loader_.GetSliceCount()))); | 165 downloadStack_.reset(new DownloadStack(static_cast<unsigned int>(loader_.GetSlicesCount()))); |
166 pendingSlices_ = loader_.GetSliceCount(); | 166 pendingSlices_ = loader_.GetSlicesCount(); |
167 | 167 |
168 for (unsigned int i = 0; i < 4; i++) // Limit to 4 simultaneous downloads | 168 for (unsigned int i = 0; i < 4; i++) // Limit to 4 simultaneous downloads |
169 { | 169 { |
170 ScheduleSliceDownload(); | 170 ScheduleSliceDownload(); |
171 } | 171 } |
261 unsigned int frame) | 261 unsigned int frame) |
262 { | 262 { |
263 loader_.ScheduleLoadFrame(instanceId, frame); | 263 loader_.ScheduleLoadFrame(instanceId, frame); |
264 } | 264 } |
265 | 265 |
266 virtual size_t GetSliceCount() const | 266 virtual size_t GetSlicesCount() const |
267 { | 267 { |
268 return loader_.GetSliceCount(); | 268 return loader_.GetSlicesCount(); |
269 } | 269 } |
270 | 270 |
271 virtual const Slice& GetSlice(size_t index) const | 271 virtual const Slice& GetSlice(size_t index) const |
272 { | 272 { |
273 return loader_.GetSlice(index); | 273 return loader_.GetSlice(index); |
315 | 315 |
316 double ComputeAxialThickness(const OrthancVolumeImage& volume) const | 316 double ComputeAxialThickness(const OrthancVolumeImage& volume) const |
317 { | 317 { |
318 double thickness; | 318 double thickness; |
319 | 319 |
320 size_t n = volume.GetSliceCount(); | 320 size_t n = volume.GetSlicesCount(); |
321 if (n > 1) | 321 if (n > 1) |
322 { | 322 { |
323 const Slice& a = volume.GetSlice(0); | 323 const Slice& a = volume.GetSlice(0); |
324 const Slice& b = volume.GetSlice(n - 1); | 324 const Slice& b = volume.GetSlice(n - 1); |
325 thickness = ((reference_.ProjectAlongNormal(b.GetGeometry().GetOrigin()) - | 325 thickness = ((reference_.ProjectAlongNormal(b.GetGeometry().GetOrigin()) - |
347 { | 347 { |
348 const Slice& axial = volume.GetSlice(0); | 348 const Slice& axial = volume.GetSlice(0); |
349 | 349 |
350 width_ = axial.GetWidth(); | 350 width_ = axial.GetWidth(); |
351 height_ = axial.GetHeight(); | 351 height_ = axial.GetHeight(); |
352 depth_ = volume.GetSliceCount(); | 352 depth_ = volume.GetSlicesCount(); |
353 | 353 |
354 pixelSpacingX_ = axial.GetPixelSpacingX(); | 354 pixelSpacingX_ = axial.GetPixelSpacingX(); |
355 pixelSpacingY_ = axial.GetPixelSpacingY(); | 355 pixelSpacingY_ = axial.GetPixelSpacingY(); |
356 sliceThickness_ = ComputeAxialThickness(volume); | 356 sliceThickness_ = ComputeAxialThickness(volume); |
357 | 357 |
362 { | 362 { |
363 const Slice& axial = volume.GetSlice(0); | 363 const Slice& axial = volume.GetSlice(0); |
364 double axialThickness = ComputeAxialThickness(volume); | 364 double axialThickness = ComputeAxialThickness(volume); |
365 | 365 |
366 width_ = axial.GetWidth(); | 366 width_ = axial.GetWidth(); |
367 height_ = static_cast<unsigned int>(volume.GetSliceCount()); | 367 height_ = static_cast<unsigned int>(volume.GetSlicesCount()); |
368 depth_ = axial.GetHeight(); | 368 depth_ = axial.GetHeight(); |
369 | 369 |
370 pixelSpacingX_ = axial.GetPixelSpacingX(); | 370 pixelSpacingX_ = axial.GetPixelSpacingX(); |
371 pixelSpacingY_ = axialThickness; | 371 pixelSpacingY_ = axialThickness; |
372 sliceThickness_ = axial.GetPixelSpacingY(); | 372 sliceThickness_ = axial.GetPixelSpacingY(); |
373 | 373 |
374 Vector origin = axial.GetGeometry().GetOrigin(); | 374 Vector origin = axial.GetGeometry().GetOrigin(); |
375 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | 375 origin += (static_cast<double>(volume.GetSlicesCount() - 1) * |
376 axialThickness * axial.GetGeometry().GetNormal()); | 376 axialThickness * axial.GetGeometry().GetNormal()); |
377 | 377 |
378 reference_ = CoordinateSystem3D(origin, | 378 reference_ = CoordinateSystem3D(origin, |
379 axial.GetGeometry().GetAxisX(), | 379 axial.GetGeometry().GetAxisX(), |
380 - axial.GetGeometry().GetNormal()); | 380 - axial.GetGeometry().GetNormal()); |
384 { | 384 { |
385 const Slice& axial = volume.GetSlice(0); | 385 const Slice& axial = volume.GetSlice(0); |
386 double axialThickness = ComputeAxialThickness(volume); | 386 double axialThickness = ComputeAxialThickness(volume); |
387 | 387 |
388 width_ = axial.GetHeight(); | 388 width_ = axial.GetHeight(); |
389 height_ = static_cast<unsigned int>(volume.GetSliceCount()); | 389 height_ = static_cast<unsigned int>(volume.GetSlicesCount()); |
390 depth_ = axial.GetWidth(); | 390 depth_ = axial.GetWidth(); |
391 | 391 |
392 pixelSpacingX_ = axial.GetPixelSpacingY(); | 392 pixelSpacingX_ = axial.GetPixelSpacingY(); |
393 pixelSpacingY_ = axialThickness; | 393 pixelSpacingY_ = axialThickness; |
394 sliceThickness_ = axial.GetPixelSpacingX(); | 394 sliceThickness_ = axial.GetPixelSpacingX(); |
395 | 395 |
396 Vector origin = axial.GetGeometry().GetOrigin(); | 396 Vector origin = axial.GetGeometry().GetOrigin(); |
397 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | 397 origin += (static_cast<double>(volume.GetSlicesCount() - 1) * |
398 axialThickness * axial.GetGeometry().GetNormal()); | 398 axialThickness * axial.GetGeometry().GetNormal()); |
399 | 399 |
400 reference_ = CoordinateSystem3D(origin, | 400 reference_ = CoordinateSystem3D(origin, |
401 axial.GetGeometry().GetAxisY(), | 401 axial.GetGeometry().GetAxisY(), |
402 axial.GetGeometry().GetNormal()); | 402 axial.GetGeometry().GetNormal()); |
404 | 404 |
405 public: | 405 public: |
406 VolumeImageGeometry(const OrthancVolumeImage& volume, | 406 VolumeImageGeometry(const OrthancVolumeImage& volume, |
407 VolumeProjection projection) | 407 VolumeProjection projection) |
408 { | 408 { |
409 if (volume.GetSliceCount() == 0) | 409 if (volume.GetSlicesCount() == 0) |
410 { | 410 { |
411 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 411 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
412 } | 412 } |
413 | 413 |
414 converter_ = volume.GetSlice(0).GetConverter(); | 414 converter_ = volume.GetSlice(0).GetConverter(); |
430 default: | 430 default: |
431 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 431 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
432 } | 432 } |
433 } | 433 } |
434 | 434 |
435 size_t GetSliceCount() const | 435 size_t GetSlicesCount() const |
436 { | 436 { |
437 return depth_; | 437 return depth_; |
438 } | 438 } |
439 | 439 |
440 const Vector& GetNormal() const | 440 const Vector& GetNormal() const |
726 { | 726 { |
727 const OrthancVolumeImage& image = | 727 const OrthancVolumeImage& image = |
728 dynamic_cast<const OrthancVolumeImage&>(message.GetOrigin()); | 728 dynamic_cast<const OrthancVolumeImage&>(message.GetOrigin()); |
729 | 729 |
730 slices_.reset(new VolumeImageGeometry(image, projection_)); | 730 slices_.reset(new VolumeImageGeometry(image, projection_)); |
731 SetSlice(slices_->GetSliceCount() / 2); | 731 SetSlice(slices_->GetSlicesCount() / 2); |
732 | 732 |
733 widget_.FitContent(); | 733 widget_.FitContent(); |
734 } | 734 } |
735 } | 735 } |
736 | 736 |
815 bool IsGeometryReady() const | 815 bool IsGeometryReady() const |
816 { | 816 { |
817 return slices_.get() != NULL; | 817 return slices_.get() != NULL; |
818 } | 818 } |
819 | 819 |
820 size_t GetSliceCount() const | 820 size_t GetSlicesCount() const |
821 { | 821 { |
822 if (slices_.get() == NULL) | 822 if (slices_.get() == NULL) |
823 { | 823 { |
824 return 0; | 824 return 0; |
825 } | 825 } |
826 else | 826 else |
827 { | 827 { |
828 return slices_->GetSliceCount(); | 828 return slices_->GetSlicesCount(); |
829 } | 829 } |
830 } | 830 } |
831 | 831 |
832 void OffsetSlice(int offset) | 832 void OffsetSlice(int offset) |
833 { | 833 { |
838 if (slice < 0) | 838 if (slice < 0) |
839 { | 839 { |
840 slice = 0; | 840 slice = 0; |
841 } | 841 } |
842 | 842 |
843 if (slice >= static_cast<int>(slices_->GetSliceCount())) | 843 if (slice >= static_cast<int>(slices_->GetSlicesCount())) |
844 { | 844 { |
845 slice = static_cast<unsigned int>(slices_->GetSliceCount()) - 1; | 845 slice = static_cast<unsigned int>(slices_->GetSlicesCount()) - 1; |
846 } | 846 } |
847 | 847 |
848 if (slice != static_cast<int>(slice_)) | 848 if (slice != static_cast<int>(slice_)) |
849 { | 849 { |
850 SetSlice(slice); | 850 SetSlice(slice); |