comparison Framework/dev.h @ 405:3942123602ba

removing ObserversRegistry
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 11 Nov 2018 17:50:11 +0100
parents 72355b637945
children 5d359b115b29
comparison
equal deleted inserted replaced
404:ba4ace20454e 405:3942123602ba
26 #include "Layers/SliceOutlineRenderer.h" 26 #include "Layers/SliceOutlineRenderer.h"
27 #include "Toolbox/DownloadStack.h" 27 #include "Toolbox/DownloadStack.h"
28 #include "Toolbox/GeometryToolbox.h" 28 #include "Toolbox/GeometryToolbox.h"
29 #include "Toolbox/OrthancSlicesLoader.h" 29 #include "Toolbox/OrthancSlicesLoader.h"
30 #include "Volumes/ImageBuffer3D.h" 30 #include "Volumes/ImageBuffer3D.h"
31 #include "Volumes/SlicedVolumeBase.h" 31 #include "Volumes/ISlicedVolume.h"
32 #include "Widgets/SliceViewerWidget.h" 32 #include "Widgets/SliceViewerWidget.h"
33 33
34 #include <Core/Logging.h> 34 #include <Core/Logging.h>
35 #include <Core/Images/ImageProcessing.h> 35 #include <Core/Images/ImageProcessing.h>
36 #include <Core/OrthancException.h>
36 37
37 #include <boost/math/special_functions/round.hpp> 38 #include <boost/math/special_functions/round.hpp>
38 39
39 40
40 namespace OrthancStone 41 namespace OrthancStone
41 { 42 {
42 // TODO: Handle errors while loading 43 // TODO: Handle errors while loading
43 class OrthancVolumeImage : 44 class OrthancVolumeImage :
44 public SlicedVolumeBase, 45 public ISlicedVolume,
45 public OrthancStone::IObserver 46 public IObserver
46 { 47 {
47 private: 48 private:
48 OrthancSlicesLoader loader_; 49 OrthancSlicesLoader loader_;
49 std::auto_ptr<ImageBuffer3D> image_; 50 std::auto_ptr<ImageBuffer3D> image_;
50 std::auto_ptr<DownloadStack> downloadStack_; 51 std::auto_ptr<DownloadStack> downloadStack_;
108 void OnSliceGeometryReady(const OrthancSlicesLoader& loader) 109 void OnSliceGeometryReady(const OrthancSlicesLoader& loader)
109 { 110 {
110 if (loader.GetSliceCount() == 0) 111 if (loader.GetSliceCount() == 0)
111 { 112 {
112 LOG(ERROR) << "Empty volume image"; 113 LOG(ERROR) << "Empty volume image";
113 SlicedVolumeBase::NotifyGeometryError(); 114 EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
114 return; 115 return;
115 } 116 }
116 117
117 for (size_t i = 1; i < loader.GetSliceCount(); i++) 118 for (size_t i = 1; i < loader.GetSliceCount(); i++)
118 { 119 {
119 if (!IsCompatible(loader.GetSlice(0), loader.GetSlice(i))) 120 if (!IsCompatible(loader.GetSlice(0), loader.GetSlice(i)))
120 { 121 {
121 SlicedVolumeBase::NotifyGeometryError(); 122 EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
122 return; 123 return;
123 } 124 }
124 } 125 }
125 126
126 double spacingZ; 127 double spacingZ;
140 { 141 {
141 if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader.GetSlice(i - 1), loader.GetSlice(i)), 142 if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader.GetSlice(i - 1), loader.GetSlice(i)),
142 0.001 /* this is expressed in mm */)) 143 0.001 /* this is expressed in mm */))
143 { 144 {
144 LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; 145 LOG(ERROR) << "The distance between successive slices is not constant in a volume image";
145 SlicedVolumeBase::NotifyGeometryError(); 146 EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
146 return; 147 return;
147 } 148 }
148 } 149 }
149 150
150 unsigned int width = loader.GetSlice(0).GetWidth(); 151 unsigned int width = loader.GetSlice(0).GetWidth();
167 ScheduleSliceDownload(); 168 ScheduleSliceDownload();
168 } 169 }
169 170
170 // TODO Check the DicomFrameConverter are constant 171 // TODO Check the DicomFrameConverter are constant
171 172
172 SlicedVolumeBase::NotifyGeometryReady(); 173 EmitMessage(ISlicedVolume::GeometryReadyMessage(*this));
173 } 174 }
174 175
175 virtual void OnSliceImageReady(const OrthancSlicesLoader& loader, 176 void OnSliceImageReady(const OrthancSlicesLoader& loader,
176 unsigned int sliceIndex, 177 unsigned int sliceIndex,
177 const Slice& slice, 178 const Slice& slice,
178 const Orthanc::ImageAccessor& image, 179 const Orthanc::ImageAccessor& image,
179 SliceImageQuality quality) 180 SliceImageQuality quality)
180 { 181 {
181 { 182 {
182 ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, sliceIndex); 183 ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, sliceIndex);
183 Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image); 184 Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image);
184 } 185 }
185 186
186 SlicedVolumeBase::NotifySliceContentChange(sliceIndex, slice); 187 EmitMessage(ISlicedVolume::SliceContentChangedMessage(*this, sliceIndex, slice));
187 188
188 if (pendingSlices_ == 1) 189 if (pendingSlices_ == 1)
189 { 190 {
190 SlicedVolumeBase::NotifyVolumeReady(); 191 EmitMessage(ISlicedVolume::VolumeReadyMessage(*this));
191 pendingSlices_ = 0; 192 pendingSlices_ = 0;
192 } 193 }
193 else if (pendingSlices_ > 1) 194 else if (pendingSlices_ > 1)
194 { 195 {
195 pendingSlices_ -= 1; 196 pendingSlices_ -= 1;
206 OnSliceGeometryReady(dynamic_cast<const OrthancSlicesLoader&>(from)); 207 OnSliceGeometryReady(dynamic_cast<const OrthancSlicesLoader&>(from));
207 break; 208 break;
208 209
209 case MessageType_SliceLoader_GeometryError: 210 case MessageType_SliceLoader_GeometryError:
210 LOG(ERROR) << "Unable to download a volume image"; 211 LOG(ERROR) << "Unable to download a volume image";
211 SlicedVolumeBase::NotifyGeometryError(); 212 EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
212 break; 213 break;
213 214
214 case MessageType_SliceLoader_ImageReady: 215 case MessageType_SliceLoader_ImageReady:
215 { 216 {
216 const OrthancSlicesLoader::SliceImageReadyMessage& msg = 217 const OrthancSlicesLoader::SliceImageReadyMessage& msg =
239 240
240 public: 241 public:
241 OrthancVolumeImage(MessageBroker& broker, 242 OrthancVolumeImage(MessageBroker& broker,
242 OrthancApiClient& orthanc, 243 OrthancApiClient& orthanc,
243 bool computeRange) : 244 bool computeRange) :
244 OrthancStone::IObserver(broker), 245 ISlicedVolume(broker),
246 IObserver(broker),
245 loader_(broker, orthanc), 247 loader_(broker, orthanc),
246 computeRange_(computeRange), 248 computeRange_(computeRange),
247 pendingSlices_(0) 249 pendingSlices_(0)
248 { 250 {
249 // TODO: replace with new callables loader_.RegisterObserver(*this); 251 // TODO: replace with new callables loader_.RegisterObserver(*this);
493 495
494 496
495 497
496 class VolumeImageMPRSlicer : 498 class VolumeImageMPRSlicer :
497 public IVolumeSlicer, 499 public IVolumeSlicer,
498 private ISlicedVolume::IObserver 500 public IObserver
499 { 501 {
500 private: 502 private:
501 class RendererFactory : public LayerReadyMessage::IRendererFactory 503 class RendererFactory : public LayerReadyMessage::IRendererFactory
502 { 504 {
503 private: 505 private:
530 532
531 bool IsGeometryReady() const 533 bool IsGeometryReady() const
532 { 534 {
533 return axialGeometry_.get() != NULL; 535 return axialGeometry_.get() != NULL;
534 } 536 }
535
536 537
537 virtual void NotifyGeometryReady(const ISlicedVolume& volume) ORTHANC_OVERRIDE 538 void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message)
538 { 539 {
540 assert(&message.GetOrigin() == &volume_);
541
539 // These 3 values are only used to speed up the IVolumeSlicer 542 // These 3 values are only used to speed up the IVolumeSlicer
540 axialGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Axial)); 543 axialGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Axial));
541 coronalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Coronal)); 544 coronalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Coronal));
542 sagittalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Sagittal)); 545 sagittalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Sagittal));
543 546
544 EmitMessage(IVolumeSlicer::GeometryReadyMessage(*this)); 547 EmitMessage(IVolumeSlicer::GeometryReadyMessage(*this));
545 } 548 }
546 549
547 virtual void NotifyGeometryError(const ISlicedVolume& volume) ORTHANC_OVERRIDE 550 void OnGeometryError(const ISlicedVolume::GeometryErrorMessage& message)
548 { 551 {
552 assert(&message.GetOrigin() == &volume_);
553
549 EmitMessage(IVolumeSlicer::GeometryErrorMessage(*this)); 554 EmitMessage(IVolumeSlicer::GeometryErrorMessage(*this));
550 } 555 }
551 556
552 virtual void NotifyContentChange(const ISlicedVolume& volume) ORTHANC_OVERRIDE 557 void OnContentChanged(const ISlicedVolume::ContentChangedMessage& message)
553 { 558 {
559 assert(&message.GetOrigin() == &volume_);
560
554 EmitMessage(IVolumeSlicer::ContentChangedMessage(*this)); 561 EmitMessage(IVolumeSlicer::ContentChangedMessage(*this));
555 } 562 }
556 563
557 virtual void NotifySliceContentChange(const ISlicedVolume& volume, 564 void OnSliceContentChanged(const ISlicedVolume::SliceContentChangedMessage& message)
558 const size_t& sliceIndex, 565 {
559 const Slice& slice) ORTHANC_OVERRIDE 566 assert(&message.GetOrigin() == &volume_);
560 { 567
561 //IVolumeSlicer::NotifySliceContentChange(slice); 568 //IVolumeSlicer::OnSliceContentChange(slice);
562 569
563 // TODO Improve this? 570 // TODO Improve this?
564 EmitMessage(IVolumeSlicer::ContentChangedMessage(*this)); 571 EmitMessage(IVolumeSlicer::ContentChangedMessage(*this));
565 }
566
567 virtual void NotifyVolumeReady(const ISlicedVolume& volume) ORTHANC_OVERRIDE
568 {
569 } 572 }
570 573
571 const VolumeImageGeometry& GetProjectionGeometry(VolumeProjection projection) 574 const VolumeImageGeometry& GetProjectionGeometry(VolumeProjection projection)
572 { 575 {
573 if (!IsGeometryReady()) 576 if (!IsGeometryReady())
627 630
628 public: 631 public:
629 VolumeImageMPRSlicer(MessageBroker& broker, 632 VolumeImageMPRSlicer(MessageBroker& broker,
630 OrthancVolumeImage& volume) : 633 OrthancVolumeImage& volume) :
631 IVolumeSlicer(broker), 634 IVolumeSlicer(broker),
635 IObserver(broker),
632 volume_(volume) 636 volume_(volume)
633 { 637 {
634 volume_.Register(*this); 638 volume_.RegisterObserverCallback(
635 } 639 new Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryReadyMessage>
636 640 (*this, &VolumeImageMPRSlicer::OnGeometryReady));
637 virtual ~VolumeImageMPRSlicer() 641
638 { 642 volume_.RegisterObserverCallback(
643 new Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryErrorMessage>
644 (*this, &VolumeImageMPRSlicer::OnGeometryError));
645
646 volume_.RegisterObserverCallback(
647 new Callable<VolumeImageMPRSlicer, ISlicedVolume::ContentChangedMessage>
648 (*this, &VolumeImageMPRSlicer::OnContentChanged));
649
650 volume_.RegisterObserverCallback(
651 new Callable<VolumeImageMPRSlicer, ISlicedVolume::SliceContentChangedMessage>
652 (*this, &VolumeImageMPRSlicer::OnSliceContentChanged));
639 } 653 }
640 654
641 virtual bool GetExtent(std::vector<Vector>& points, 655 virtual bool GetExtent(std::vector<Vector>& points,
642 const CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE 656 const CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE
643 { 657 {
700 }; 714 };
701 715
702 716
703 class VolumeImageInteractor : 717 class VolumeImageInteractor :
704 public IWorldSceneInteractor, 718 public IWorldSceneInteractor,
705 protected ISlicedVolume::IObserver 719 public IObserver
706 { 720 {
707 private: 721 private:
708 SliceViewerWidget& widget_; 722 SliceViewerWidget& widget_;
709 VolumeProjection projection_; 723 VolumeProjection projection_;
710 std::auto_ptr<VolumeImageGeometry> slices_; 724 std::auto_ptr<VolumeImageGeometry> slices_;
711 size_t slice_; 725 size_t slice_;
712 726
713 protected: 727 protected:
714 virtual void NotifyGeometryReady(const ISlicedVolume& volume) 728 void OnGeometryReady(const ISlicedVolume::GeometryReadyMessage& message)
715 { 729 {
716 if (slices_.get() == NULL) 730 if (slices_.get() == NULL)
717 { 731 {
718 const OrthancVolumeImage& image = dynamic_cast<const OrthancVolumeImage&>(volume); 732 const OrthancVolumeImage& image =
733 dynamic_cast<const OrthancVolumeImage&>(message.GetOrigin());
719 734
720 slices_.reset(new VolumeImageGeometry(image, projection_)); 735 slices_.reset(new VolumeImageGeometry(image, projection_));
721 SetSlice(slices_->GetSliceCount() / 2); 736 SetSlice(slices_->GetSliceCount() / 2);
722 737
723 widget_.FitContent(); 738 widget_.FitContent();
724 } 739 }
725 }
726
727 virtual void NotifyGeometryError(const ISlicedVolume& volume)
728 {
729 }
730
731 virtual void NotifyContentChange(const ISlicedVolume& volume)
732 {
733 }
734
735 virtual void NotifySliceContentChange(const ISlicedVolume& volume,
736 const size_t& sliceIndex,
737 const Slice& slice)
738 {
739 }
740
741 virtual void NotifyVolumeReady(const ISlicedVolume& volume)
742 {
743 } 740 }
744 741
745 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, 742 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
746 const ViewportGeometry& view, 743 const ViewportGeometry& view,
747 MouseButton button, 744 MouseButton button,
799 break; 796 break;
800 } 797 }
801 } 798 }
802 799
803 public: 800 public:
804 VolumeImageInteractor(OrthancVolumeImage& volume, 801 VolumeImageInteractor(MessageBroker& broker,
802 OrthancVolumeImage& volume,
805 SliceViewerWidget& widget, 803 SliceViewerWidget& widget,
806 VolumeProjection projection) : 804 VolumeProjection projection) :
805 IObserver(broker),
807 widget_(widget), 806 widget_(widget),
808 projection_(projection) 807 projection_(projection)
809 { 808 {
810 volume.Register(*this);
811 widget.SetInteractor(*this); 809 widget.SetInteractor(*this);
810
811 volume.RegisterObserverCallback(
812 new Callable<VolumeImageInteractor, ISlicedVolume::GeometryReadyMessage>
813 (*this, &VolumeImageInteractor::OnGeometryReady));
812 } 814 }
813 815
814 bool IsGeometryReady() const 816 bool IsGeometryReady() const
815 { 817 {
816 return slices_.get() != NULL; 818 return slices_.get() != NULL;