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);