Mercurial > hg > orthanc-stone
comparison Framework/dev.h @ 119:ba83e38cf3ff wasm
rendering of rt-dose
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 02 Oct 2017 22:01:41 +0200 |
parents | 42c05a3baee3 |
children | 063f7f3d9f14 |
comparison
equal
deleted
inserted
replaced
118:a4d0b6c82b29 | 119:ba83e38cf3ff |
---|---|
45 { | 45 { |
46 private: | 46 private: |
47 OrthancSlicesLoader loader_; | 47 OrthancSlicesLoader loader_; |
48 std::auto_ptr<ImageBuffer3D> image_; | 48 std::auto_ptr<ImageBuffer3D> image_; |
49 std::auto_ptr<DownloadStack> downloadStack_; | 49 std::auto_ptr<DownloadStack> downloadStack_; |
50 | 50 bool computeRange_; |
51 | 51 |
52 void ScheduleSliceDownload() | 52 void ScheduleSliceDownload() |
53 { | 53 { |
54 assert(downloadStack_.get() != NULL); | 54 assert(downloadStack_.get() != NULL); |
55 | 55 |
149 unsigned int height = loader.GetSlice(0).GetHeight(); | 149 unsigned int height = loader.GetSlice(0).GetHeight(); |
150 Orthanc::PixelFormat format = loader.GetSlice(0).GetConverter().GetExpectedPixelFormat(); | 150 Orthanc::PixelFormat format = loader.GetSlice(0).GetConverter().GetExpectedPixelFormat(); |
151 LOG(INFO) << "Creating a volume image of size " << width << "x" << height | 151 LOG(INFO) << "Creating a volume image of size " << width << "x" << height |
152 << "x" << loader.GetSliceCount() << " in " << Orthanc::EnumerationToString(format); | 152 << "x" << loader.GetSliceCount() << " in " << Orthanc::EnumerationToString(format); |
153 | 153 |
154 image_.reset(new ImageBuffer3D(format, width, height, loader.GetSliceCount())); | 154 image_.reset(new ImageBuffer3D(format, width, height, loader.GetSliceCount(), computeRange_)); |
155 image_->SetAxialGeometry(loader.GetSlice(0).GetGeometry()); | 155 image_->SetAxialGeometry(loader.GetSlice(0).GetGeometry()); |
156 image_->SetVoxelDimensions(loader.GetSlice(0).GetPixelSpacingX(), | 156 image_->SetVoxelDimensions(loader.GetSlice(0).GetPixelSpacingX(), |
157 loader.GetSlice(0).GetPixelSpacingY(), spacingZ); | 157 loader.GetSlice(0).GetPixelSpacingY(), spacingZ); |
158 image_->Clear(); | 158 image_->Clear(); |
159 | 159 |
199 LOG(ERROR) << "Cannot download slice " << sliceIndex << " in a volume image"; | 199 LOG(ERROR) << "Cannot download slice " << sliceIndex << " in a volume image"; |
200 ScheduleSliceDownload(); | 200 ScheduleSliceDownload(); |
201 } | 201 } |
202 | 202 |
203 public: | 203 public: |
204 OrthancVolumeImage(IWebService& orthanc) : | 204 OrthancVolumeImage(IWebService& orthanc, |
205 loader_(*this, orthanc) | 205 bool computeRange) : |
206 loader_(*this, orthanc), | |
207 computeRange_(computeRange) | |
206 { | 208 { |
207 } | 209 } |
208 | 210 |
209 void ScheduleLoadSeries(const std::string& seriesId) | 211 void ScheduleLoadSeries(const std::string& seriesId) |
210 { | 212 { |
240 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 242 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
241 } | 243 } |
242 else | 244 else |
243 { | 245 { |
244 return *image_; | 246 return *image_; |
247 } | |
248 } | |
249 | |
250 bool FitWindowingToRange(RenderStyle& style, | |
251 const DicomFrameConverter& converter) const | |
252 { | |
253 if (image_.get() == NULL) | |
254 { | |
255 return false; | |
256 } | |
257 else | |
258 { | |
259 return image_->FitWindowingToRange(style, converter); | |
245 } | 260 } |
246 } | 261 } |
247 }; | 262 }; |
248 | 263 |
249 | 264 |
320 Vector origin = axial.GetGeometry().GetOrigin(); | 335 Vector origin = axial.GetGeometry().GetOrigin(); |
321 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | 336 origin += (static_cast<double>(volume.GetSliceCount() - 1) * |
322 axialThickness * axial.GetGeometry().GetNormal()); | 337 axialThickness * axial.GetGeometry().GetNormal()); |
323 | 338 |
324 reference_ = CoordinateSystem3D(origin, | 339 reference_ = CoordinateSystem3D(origin, |
325 axial.GetGeometry().GetAxisX(), | 340 axial.GetGeometry().GetAxisX(), |
326 -axial.GetGeometry().GetNormal()); | 341 -axial.GetGeometry().GetNormal()); |
327 } | 342 } |
328 | 343 |
329 void SetupSagittal(const OrthancVolumeImage& volume) | 344 void SetupSagittal(const OrthancVolumeImage& volume) |
330 { | 345 { |
331 const Slice& axial = volume.GetSlice(0); | 346 const Slice& axial = volume.GetSlice(0); |
342 Vector origin = axial.GetGeometry().GetOrigin(); | 357 Vector origin = axial.GetGeometry().GetOrigin(); |
343 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | 358 origin += (static_cast<double>(volume.GetSliceCount() - 1) * |
344 axialThickness * axial.GetGeometry().GetNormal()); | 359 axialThickness * axial.GetGeometry().GetNormal()); |
345 | 360 |
346 reference_ = CoordinateSystem3D(origin, | 361 reference_ = CoordinateSystem3D(origin, |
347 axial.GetGeometry().GetAxisY(), | 362 axial.GetGeometry().GetAxisY(), |
348 axial.GetGeometry().GetNormal()); | 363 axial.GetGeometry().GetNormal()); |
349 } | 364 } |
350 | 365 |
351 public: | 366 public: |
352 VolumeImageGeometry(const OrthancVolumeImage& volume, | 367 VolumeImageGeometry(const OrthancVolumeImage& volume, |
353 VolumeProjection projection) | 368 VolumeProjection projection) |
374 break; | 389 break; |
375 | 390 |
376 default: | 391 default: |
377 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 392 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
378 } | 393 } |
394 | |
395 //sliceThickness_ = 3.0f; // TODO XXXXX | |
379 } | 396 } |
380 | 397 |
381 size_t GetSliceCount() const | 398 size_t GetSliceCount() const |
382 { | 399 { |
383 return depth_; | 400 return depth_; |
414 index = static_cast<size_t>(s); | 431 index = static_cast<size_t>(s); |
415 return true; | 432 return true; |
416 } | 433 } |
417 } | 434 } |
418 | 435 |
419 Slice GetSlice(size_t slice) const | 436 Slice* GetSlice(size_t slice) const |
420 { | 437 { |
421 if (slice < 0 || | 438 if (slice < 0 || |
422 slice >= depth_) | 439 slice >= depth_) |
423 { | 440 { |
424 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 441 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
425 } | 442 } |
426 else | 443 else |
427 { | 444 { |
428 CoordinateSystem3D origin(reference_.GetOrigin() + | 445 CoordinateSystem3D origin(reference_.GetOrigin() + |
429 static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), | 446 static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), |
430 reference_.GetAxisX(), | 447 reference_.GetAxisX(), |
431 reference_.GetAxisY()); | 448 reference_.GetAxisY()); |
432 | 449 |
433 return Slice(origin, pixelSpacingX_, pixelSpacingY_, sliceThickness_, | 450 return new Slice(origin, pixelSpacingX_, pixelSpacingY_, sliceThickness_, |
434 width_, height_, converter_); | 451 width_, height_, converter_); |
435 } | 452 } |
436 } | 453 } |
437 }; | 454 }; |
438 | 455 |
439 | 456 |
562 } | 579 } |
563 else | 580 else |
564 { | 581 { |
565 // As the slices of the volumic image are arranged in a box, | 582 // As the slices of the volumic image are arranged in a box, |
566 // we only consider one single reference slice (the one with index 0). | 583 // we only consider one single reference slice (the one with index 0). |
567 GetProjectionGeometry(projection).GetSlice(0).GetExtent(points); | 584 std::auto_ptr<Slice> slice(GetProjectionGeometry(projection).GetSlice(0)); |
585 slice->GetExtent(points); | |
568 | 586 |
569 return true; | 587 return true; |
570 } | 588 } |
571 } | 589 } |
572 | 590 |
593 | 611 |
594 // TODO Transfer ownership if non-axial, to avoid memcpy | 612 // TODO Transfer ownership if non-axial, to avoid memcpy |
595 frame.reset(Orthanc::Image::Clone(reader.GetAccessor())); | 613 frame.reset(Orthanc::Image::Clone(reader.GetAccessor())); |
596 } | 614 } |
597 | 615 |
598 Slice slice = geometry.GetSlice(closest); | 616 std::auto_ptr<Slice> slice(geometry.GetSlice(closest)); |
599 LayerSourceBase::NotifyLayerReady( | 617 LayerSourceBase::NotifyLayerReady( |
600 FrameRenderer::CreateRenderer(frame.release(), slice, isFullQuality), | 618 FrameRenderer::CreateRenderer(frame.release(), *slice, isFullQuality), |
601 //new SliceOutlineRenderer(slice), | 619 //new SliceOutlineRenderer(slice), |
602 slice, false); | 620 *slice, false); |
603 return; | 621 return; |
604 } | 622 } |
605 } | 623 } |
606 | 624 |
607 // Error | 625 // Error |
611 }; | 629 }; |
612 | 630 |
613 | 631 |
614 class VolumeImageInteractor : | 632 class VolumeImageInteractor : |
615 public IWorldSceneInteractor, | 633 public IWorldSceneInteractor, |
616 private ISlicedVolume::IObserver | 634 protected ISlicedVolume::IObserver |
617 { | 635 { |
618 private: | 636 private: |
619 LayerWidget& widget_; | 637 LayerWidget& widget_; |
620 VolumeProjection projection_; | 638 VolumeProjection projection_; |
621 std::auto_ptr<VolumeImageGeometry> slices_; | 639 std::auto_ptr<VolumeImageGeometry> slices_; |
622 size_t slice_; | 640 size_t slice_; |
623 | 641 |
642 protected: | |
624 virtual void NotifyGeometryReady(const ISlicedVolume& volume) | 643 virtual void NotifyGeometryReady(const ISlicedVolume& volume) |
625 { | 644 { |
626 if (slices_.get() == NULL) | 645 if (slices_.get() == NULL) |
627 { | 646 { |
628 const OrthancVolumeImage& image = dynamic_cast<const OrthancVolumeImage&>(volume); | 647 const OrthancVolumeImage& image = dynamic_cast<const OrthancVolumeImage&>(volume); |
759 void SetSlice(size_t slice) | 778 void SetSlice(size_t slice) |
760 { | 779 { |
761 if (slices_.get() != NULL) | 780 if (slices_.get() != NULL) |
762 { | 781 { |
763 slice_ = slice; | 782 slice_ = slice; |
764 widget_.SetSlice(slices_->GetSlice(slice_).GetGeometry()); | 783 |
784 std::auto_ptr<Slice> tmp(slices_->GetSlice(slice_)); | |
785 widget_.SetSlice(tmp->GetGeometry()); | |
765 } | 786 } |
766 } | 787 } |
767 }; | 788 }; |
768 | 789 |
769 | 790 |