changeset 406:5d359b115b29

use of callables in OrthancVolumeImage
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 11 Nov 2018 18:17:50 +0100
parents 3942123602ba
children 842a3c7cfdc0
files Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Applications/Samples/SimpleViewerApplicationSingleFile.h Framework/Messages/IMessage.h Framework/SmartLoader.cpp Framework/Toolbox/OrthancSlicesLoader.cpp Framework/Toolbox/OrthancSlicesLoader.h Framework/dev.h TODO
diffstat 8 files changed, 85 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp	Sun Nov 11 17:50:11 2018 +0100
+++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp	Sun Nov 11 18:17:50 2018 +0100
@@ -170,7 +170,8 @@
 
   void SimpleViewerApplication::OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message)
   {
-    message.GetOrigin().FitContent();
+    // TODO: The "const_cast" could probably be replaced by "mainWidget_"
+    const_cast<SliceViewerWidget&>(message.GetOrigin()).FitContent();
   }
 
   void SimpleViewerApplication::SelectSeriesInMainViewport(const std::string& seriesId)
--- a/Applications/Samples/SimpleViewerApplicationSingleFile.h	Sun Nov 11 17:50:11 2018 +0100
+++ b/Applications/Samples/SimpleViewerApplicationSingleFile.h	Sun Nov 11 18:17:50 2018 +0100
@@ -407,7 +407,8 @@
 
       void OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message)
       {
-        message.GetOrigin().FitContent();
+        // TODO: The "const_cast" could probably be replaced by "mainWidget"
+        const_cast<SliceViewerWidget&>(message.GetOrigin()).FitContent();
       }
 
       void SelectSeriesInMainViewport(const std::string& seriesId)
--- a/Framework/Messages/IMessage.h	Sun Nov 11 17:50:11 2018 +0100
+++ b/Framework/Messages/IMessage.h	Sun Nov 11 18:17:50 2018 +0100
@@ -89,16 +89,16 @@
   class OriginMessage : public BaseMessage<type>
   {
   private:
-    TOrigin& origin_;
+    const TOrigin& origin_;
 
   public:
-    OriginMessage(TOrigin& origin) :
+    OriginMessage(const TOrigin& origin) :
       BaseMessage<type>(),
       origin_(origin)
     {
     }
 
-    TOrigin& GetOrigin() const
+    const TOrigin& GetOrigin() const
     {
       return origin_;
     }
--- a/Framework/SmartLoader.cpp	Sun Nov 11 17:50:11 2018 +0100
+++ b/Framework/SmartLoader.cpp	Sun Nov 11 18:17:50 2018 +0100
@@ -224,7 +224,8 @@
 
   void SmartLoader::OnLayerGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message)
   {
-    DicomSeriesVolumeSlicer& source = dynamic_cast<DicomSeriesVolumeSlicer&>(message.GetOrigin());
+    const DicomSeriesVolumeSlicer& source =
+      dynamic_cast<const DicomSeriesVolumeSlicer&>(message.GetOrigin());
 
     // save/replace the slice in cache
     const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount()
@@ -269,7 +270,9 @@
 
   void SmartLoader::OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message)
   {
-    DicomSeriesVolumeSlicer& source = dynamic_cast<DicomSeriesVolumeSlicer&>(message.GetOrigin());
+    const DicomSeriesVolumeSlicer& source =
+      dynamic_cast<const DicomSeriesVolumeSlicer&>(message.GetOrigin());
+    
     const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ?
     std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + 
                               boost::lexical_cast<std::string>(slice.GetFrame()));
--- a/Framework/Toolbox/OrthancSlicesLoader.cpp	Sun Nov 11 17:50:11 2018 +0100
+++ b/Framework/Toolbox/OrthancSlicesLoader.cpp	Sun Nov 11 18:17:50 2018 +0100
@@ -175,14 +175,16 @@
   void OrthancSlicesLoader::NotifySliceImageSuccess(const Operation& operation,
                                                     const Orthanc::ImageAccessor& image)
   {
-    OrthancSlicesLoader::SliceImageReadyMessage msg(operation.GetSliceIndex(), operation.GetSlice(), image, operation.GetQuality());
+    OrthancSlicesLoader::SliceImageReadyMessage msg
+      (*this, operation.GetSliceIndex(), operation.GetSlice(), image, operation.GetQuality());
     EmitMessage(msg);
   }
   
   
   void OrthancSlicesLoader::NotifySliceImageError(const Operation& operation)
   {
-    OrthancSlicesLoader::SliceImageErrorMessage msg(operation.GetSliceIndex(), operation.GetSlice(), operation.GetQuality());
+    OrthancSlicesLoader::SliceImageErrorMessage msg
+      (*this, operation.GetSliceIndex(), operation.GetSlice(), operation.GetQuality());
     EmitMessage(msg);
   }
   
--- a/Framework/Toolbox/OrthancSlicesLoader.h	Sun Nov 11 17:50:11 2018 +0100
+++ b/Framework/Toolbox/OrthancSlicesLoader.h	Sun Nov 11 18:17:50 2018 +0100
@@ -39,7 +39,8 @@
     typedef OriginMessage<MessageType_SliceLoader_GeometryReady, OrthancSlicesLoader> SliceGeometryReadyMessage;
     typedef OriginMessage<MessageType_SliceLoader_GeometryError, OrthancSlicesLoader> SliceGeometryErrorMessage;
 
-    class SliceImageReadyMessage : public BaseMessage<MessageType_SliceLoader_ImageReady>
+    class SliceImageReadyMessage :
+      public OriginMessage<MessageType_SliceLoader_ImageReady, OrthancSlicesLoader>
     {
     private:
       unsigned int                   sliceIndex_;
@@ -48,10 +49,12 @@
       SliceImageQuality              effectiveQuality_;
 
     public:
-      SliceImageReadyMessage(unsigned int sliceIndex,
+      SliceImageReadyMessage(const OrthancSlicesLoader& origin,
+                             unsigned int sliceIndex,
                              const Slice& slice,
                              const Orthanc::ImageAccessor& image,
                              SliceImageQuality effectiveQuality) :
+        OriginMessage(origin),
         sliceIndex_(sliceIndex),
         slice_(slice),
         image_(image),
@@ -81,7 +84,8 @@
     };
     
 
-    class SliceImageErrorMessage : public BaseMessage<MessageType_SliceLoader_ImageError>
+    class SliceImageErrorMessage : 
+      public OriginMessage<MessageType_SliceLoader_ImageError, OrthancSlicesLoader>
     {
     private:
       const Slice&       slice_;
@@ -89,9 +93,11 @@
       SliceImageQuality  effectiveQuality_;
 
     public:
-      SliceImageErrorMessage(unsigned int sliceIndex,
+      SliceImageErrorMessage(const OrthancSlicesLoader& origin,
+                             unsigned int sliceIndex,
                              const Slice& slice,
                              SliceImageQuality effectiveQuality) :
+        OriginMessage(origin),
         slice_(slice),
         sliceIndex_(sliceIndex),
         effectiveQuality_(effectiveQuality)
--- a/Framework/dev.h	Sun Nov 11 17:50:11 2018 +0100
+++ b/Framework/dev.h	Sun Nov 11 18:17:50 2018 +0100
@@ -106,18 +106,20 @@
     }
 
 
-    void OnSliceGeometryReady(const OrthancSlicesLoader& loader)
+    void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message)
     {
-      if (loader.GetSliceCount() == 0)
+      assert(&message.GetOrigin() == &loader_);
+      
+      if (loader_.GetSliceCount() == 0)
       {
         LOG(ERROR) << "Empty volume image";
         EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
         return;
       }
 
-      for (size_t i = 1; i < loader.GetSliceCount(); i++)
+      for (size_t i = 1; i < loader_.GetSliceCount(); i++)
       {
-        if (!IsCompatible(loader.GetSlice(0), loader.GetSlice(i)))
+        if (!IsCompatible(loader_.GetSlice(0), loader_.GetSlice(i)))
         {
           EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
           return;
@@ -126,9 +128,9 @@
 
       double spacingZ;
 
-      if (loader.GetSliceCount() > 1)
+      if (loader_.GetSliceCount() > 1)
       {
-        spacingZ = GetDistance(loader.GetSlice(0), loader.GetSlice(1));
+        spacingZ = GetDistance(loader_.GetSlice(0), loader_.GetSlice(1));
       }
       else
       {
@@ -137,9 +139,9 @@
         spacingZ = 1;
       }
 
-      for (size_t i = 1; i < loader.GetSliceCount(); i++)
+      for (size_t i = 1; i < loader_.GetSliceCount(); i++)
       {
-        if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader.GetSlice(i - 1), loader.GetSlice(i)),
+        if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)),
                                    0.001 /* this is expressed in mm */))
         {
           LOG(ERROR) << "The distance between successive slices is not constant in a volume image";
@@ -148,20 +150,20 @@
         }
       }
 
-      unsigned int width = loader.GetSlice(0).GetWidth();
-      unsigned int height = loader.GetSlice(0).GetHeight();
-      Orthanc::PixelFormat format = loader.GetSlice(0).GetConverter().GetExpectedPixelFormat();
+      unsigned int width = loader_.GetSlice(0).GetWidth();
+      unsigned int height = loader_.GetSlice(0).GetHeight();
+      Orthanc::PixelFormat format = loader_.GetSlice(0).GetConverter().GetExpectedPixelFormat();
       LOG(INFO) << "Creating a volume image of size " << width << "x" << height
-                << "x" << loader.GetSliceCount() << " in " << Orthanc::EnumerationToString(format);
+                << "x" << loader_.GetSliceCount() << " in " << Orthanc::EnumerationToString(format);
 
-      image_.reset(new ImageBuffer3D(format, width, height, loader.GetSliceCount(), computeRange_));
-      image_->SetAxialGeometry(loader.GetSlice(0).GetGeometry());
-      image_->SetVoxelDimensions(loader.GetSlice(0).GetPixelSpacingX(),
-                                 loader.GetSlice(0).GetPixelSpacingY(), spacingZ);
+      image_.reset(new ImageBuffer3D(format, width, height, loader_.GetSliceCount(), computeRange_));
+      image_->SetAxialGeometry(loader_.GetSlice(0).GetGeometry());
+      image_->SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(),
+                                 loader_.GetSlice(0).GetPixelSpacingY(), spacingZ);
       image_->Clear();
 
-      downloadStack_.reset(new DownloadStack(loader.GetSliceCount()));
-      pendingSlices_ = loader.GetSliceCount();
+      downloadStack_.reset(new DownloadStack(loader_.GetSliceCount()));
+      pendingSlices_ = loader_.GetSliceCount();
 
       for (unsigned int i = 0; i < 4; i++)  // Limit to 4 simultaneous downloads
       {
@@ -173,18 +175,27 @@
       EmitMessage(ISlicedVolume::GeometryReadyMessage(*this));
     }
 
-    void OnSliceImageReady(const OrthancSlicesLoader& loader,
-                           unsigned int sliceIndex,
-                           const Slice& slice,
-                           const Orthanc::ImageAccessor& image,
-                           SliceImageQuality quality)
+    
+    void OnSliceGeometryError(const OrthancSlicesLoader::SliceGeometryErrorMessage& message)
     {
+      assert(&message.GetOrigin() == &loader_);
+
+      LOG(ERROR) << "Unable to download a volume image";
+      EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
+    }
+
+    
+    void OnSliceImageReady(const OrthancSlicesLoader::SliceImageReadyMessage& message)
+    {
+      assert(&message.GetOrigin() == &loader_);
+
       {
-        ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, sliceIndex);
-        Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image);
+        ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, message.GetSliceIndex());
+        Orthanc::ImageProcessing::Copy(writer.GetAccessor(), message.GetImage());
       }
 
-      EmitMessage(ISlicedVolume::SliceContentChangedMessage(*this, sliceIndex, slice));
+      EmitMessage(ISlicedVolume::SliceContentChangedMessage
+                  (*this, message.GetSliceIndex(), message.GetSlice()));
 
       if (pendingSlices_ == 1)
       {
@@ -199,45 +210,16 @@
       ScheduleSliceDownload();
     }
 
-    virtual void HandleMessage(const IObservable& from, const IMessage& message)
+    
+    void OnSliceImageError(const OrthancSlicesLoader::SliceImageErrorMessage& message)
     {
-      switch (message.GetType())
-      {
-        case MessageType_SliceLoader_GeometryReady:
-          OnSliceGeometryReady(dynamic_cast<const OrthancSlicesLoader&>(from));
-          break;
-        
-        case MessageType_SliceLoader_GeometryError:
-          LOG(ERROR) << "Unable to download a volume image";
-          EmitMessage(ISlicedVolume::GeometryErrorMessage(*this));
-          break;
-        
-        case MessageType_SliceLoader_ImageReady:
-        {
-          const OrthancSlicesLoader::SliceImageReadyMessage& msg =
-            dynamic_cast<const OrthancSlicesLoader::SliceImageReadyMessage&>(message);
-          OnSliceImageReady(dynamic_cast<const OrthancSlicesLoader&>(from),
-                            msg.GetSliceIndex(),
-                            msg.GetSlice(),
-                            msg.GetImage(),
-                            msg.GetEffectiveQuality());
-          break;
-        }
-      
-        case MessageType_SliceLoader_ImageError:
-        {
-          const OrthancSlicesLoader::SliceImageErrorMessage& msg =
-            dynamic_cast<const OrthancSlicesLoader::SliceImageErrorMessage&>(message);
-          LOG(ERROR) << "Cannot download slice " << msg.GetSliceIndex() << " in a volume image";
-          ScheduleSliceDownload();
-          break;
-        }
-      
-        default:
-          VLOG("unhandled message type" << message.GetType());
-      }
+      assert(&message.GetOrigin() == &loader_);
+
+      LOG(ERROR) << "Cannot download slice " << message.GetSliceIndex() << " in a volume image";
+      ScheduleSliceDownload();
     }
 
+
   public:
     OrthancVolumeImage(MessageBroker& broker,
                        OrthancApiClient& orthanc,
@@ -248,7 +230,21 @@
       computeRange_(computeRange),
       pendingSlices_(0)
     {
-      // TODO: replace with new callables loader_.RegisterObserver(*this);
+      loader_.RegisterObserverCallback(
+        new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryReadyMessage>
+        (*this, &OrthancVolumeImage::OnSliceGeometryReady));
+
+      loader_.RegisterObserverCallback(
+        new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryErrorMessage>
+        (*this, &OrthancVolumeImage::OnSliceGeometryError));
+
+      loader_.RegisterObserverCallback(
+        new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageReadyMessage>
+        (*this, &OrthancVolumeImage::OnSliceImageReady));
+
+      loader_.RegisterObserverCallback(
+        new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageErrorMessage>
+        (*this, &OrthancVolumeImage::OnSliceImageError));
     }
 
     void ScheduleLoadSeries(const std::string& seriesId)
--- a/TODO	Sun Nov 11 17:50:11 2018 +0100
+++ b/TODO	Sun Nov 11 18:17:50 2018 +0100
@@ -45,7 +45,6 @@
 Source code cosmetics
 ---------------------
 
-* Remove #include "OrthancException.h" in "ObserversRegistry.h"
 * Use "SampleInteractor::AddWidget()" in all samples