diff Applications/Samples/SingleVolumeApplication.h @ 102:fcec0ab44054 wasm

display volumes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 31 May 2017 17:01:18 +0200
parents b340879da9bd
children 474d85e76499
line wrap: on
line diff
--- a/Applications/Samples/SingleVolumeApplication.h	Wed May 31 10:35:20 2017 +0200
+++ b/Applications/Samples/SingleVolumeApplication.h	Wed May 31 17:01:18 2017 +0200
@@ -21,7 +21,10 @@
 
 #pragma once
 
-#include "SampleInteractor.h"
+#include "SampleApplicationBase.h"
+#include "../../Framework/dev.h"
+//#include "SampleInteractor.h"
+#include "../../Framework/Widgets/LayerWidget.h"
 
 #include "../../Resources/Orthanc/Core/Toolbox.h"
 #include "../../Framework/Layers/LineMeasureTracker.h"
@@ -32,9 +35,160 @@
 {
   namespace Samples
   {
-    class SingleVolumeApplication : public SampleApplicationBase
+    class SingleVolumeApplication :
+      public SampleApplicationBase,
+      private ILayerSource::IObserver
     {
     private:
+      class Interactor : public IWorldSceneInteractor
+      {
+      private:
+        SingleVolumeApplication&  application_;
+        
+      public:
+        Interactor(SingleVolumeApplication&  application) :
+          application_(application)
+        {
+        }
+        
+        virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
+                                                            const ViewportGeometry& view,
+                                                            MouseButton button,
+                                                            double x,
+                                                            double y,
+                                                            IStatusBar* statusBar)
+        {
+          return NULL;
+        }
+
+        virtual void MouseOver(CairoContext& context,
+                               WorldSceneWidget& widget,
+                               const ViewportGeometry& view,
+                               double x,
+                               double y,
+                               IStatusBar* statusBar)
+        {
+          if (statusBar != NULL)
+          {
+            Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y);
+            
+            char buf[64];
+            sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", 
+                    p[0] / 10.0, p[1] / 10.0, p[2] / 10.0);
+            statusBar->SetMessage(buf);
+          }
+        }
+
+        virtual void MouseWheel(WorldSceneWidget& widget,
+                                MouseWheelDirection direction,
+                                KeyboardModifiers modifiers,
+                                IStatusBar* statusBar)
+        {
+          int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1);
+          
+          switch (direction)
+          {
+            case MouseWheelDirection_Up:
+              application_.OffsetSlice(-scale);
+              break;
+
+            case MouseWheelDirection_Down:
+              application_.OffsetSlice(scale);
+              break;
+
+            default:
+              break;
+          }
+        }
+
+        virtual void KeyPressed(WorldSceneWidget& widget,
+                                char key,
+                                KeyboardModifiers modifiers,
+                                IStatusBar* statusBar)
+        {
+          switch (key)
+          {
+            case 's':
+              widget.SetDefaultView();
+              break;
+
+            default:
+              break;
+          }
+        }
+      };
+
+
+      LayerWidget*                        widget_;
+      OrthancVolumeImage*                 volume_;
+      VolumeProjection                    projection_;
+      std::auto_ptr<VolumeImageGeometry>  slices_;
+      size_t                              slice_;
+
+      void OffsetSlice(int offset)
+      {
+        if (slices_.get() != NULL)
+        {
+          int slice = static_cast<int>(slice_) + offset;
+
+          if (slice < 0)
+          {
+            slice = 0;
+          }
+
+          if (slice >= static_cast<int>(slices_->GetSliceCount()))
+          {
+            slice = slices_->GetSliceCount() - 1;
+          }
+
+          if (slice != static_cast<int>(slice_)) 
+          {
+            SetSlice(slice);
+          }   
+        }
+      }
+      
+      void SetSlice(size_t slice)
+      {
+        if (slices_.get() != NULL)
+        {
+          slice_ = slice;
+          widget_->SetSlice(slices_->GetSlice(slice_).GetGeometry());
+        }
+      }
+      
+      virtual void NotifyGeometryReady(const ILayerSource& source)
+      {
+        if (slices_.get() == NULL)
+        {
+          slices_.reset(new VolumeImageGeometry(*volume_, projection_));
+          SetSlice(slices_->GetSliceCount() / 2);
+          
+          widget_->SetDefaultView();
+        }
+      }
+      
+      virtual void NotifyGeometryError(const ILayerSource& source)
+      {
+      }
+      
+      virtual void NotifyContentChange(const ILayerSource& source)
+      {
+      }
+
+      virtual void NotifySliceChange(const ILayerSource& source,
+                                     const Slice& slice)
+      {
+      }
+ 
+      virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
+                                    const ILayerSource& source,
+                                    const Slice& slice,
+                                    bool isError)
+      {
+      }
+
+#if 0
       class Interactor : public SampleInteractor
       {
       private:
@@ -204,9 +358,16 @@
           }
         }
       };
-
+#endif
 
+      
     public:
+      SingleVolumeApplication() : 
+        widget_(NULL),
+        volume_(NULL)
+      {
+      }
+      
       virtual void DeclareCommandLineOptions(boost::program_options::options_description& options)
       {
         boost::program_options::options_description generic("Sample options");
@@ -243,18 +404,17 @@
         std::string tmp = parameters["projection"].as<std::string>();
         Orthanc::Toolbox::ToLowerCase(tmp);
         
-        VolumeProjection projection;
         if (tmp == "axial")
         {
-          projection = VolumeProjection_Axial;
+          projection_ = VolumeProjection_Axial;
         }
         else if (tmp == "sagittal")
         {
-          projection = VolumeProjection_Sagittal;
+          projection_ = VolumeProjection_Sagittal;
         }
         else if (tmp == "coronal")
         {
-          projection = VolumeProjection_Coronal;
+          projection_ = VolumeProjection_Coronal;
         }
         else
         {
@@ -262,22 +422,74 @@
           throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
         }
 
-        VolumeImage& volume = context.AddSeriesVolume(series, true /* progressive download */, threads);
+        std::auto_ptr<LayerWidget> widget(new LayerWidget);
+        widget_ = widget.get();
+
+#if 0
+        std::auto_ptr<OrthancVolumeImage> volume(new OrthancVolumeImage(context.GetWebService()));
+        volume->ScheduleLoadSeries(series);
 
-        std::auto_ptr<Interactor> interactor(new Interactor(volume, projection, reverse));
+        volume_ = volume.get();
+        
+        {
+          std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*volume));
+          source->Register(*this);
+          widget->AddLayer(source.release());
+        }
+
+        context.AddVolume(volume.release());
+#else
+        std::auto_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context.GetWebService()));
+        ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d");
+
+        std::auto_ptr<OrthancVolumeImage> pet(new OrthancVolumeImage(context.GetWebService()));
+        pet->ScheduleLoadSeries("aabad2e7-80702b5d-e599d26c-4f13398e-38d58a9e");
 
-        std::auto_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget);
-        widget->AddLayer(new VolumeImage::LayerFactory(volume));
-        widget->SetSlice(interactor->GetCursor().GetCurrentSlice());
-        widget->SetInteractor(*interactor);
+        volume_ = pet.get();
+        
+        {
+          std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*ct));
+          //source->Register(*this);
+          widget->AddLayer(source.release());
+        }
+
+        {
+          std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*pet));
+          source->Register(*this);
+          widget->AddLayer(source.release());
+        }
+
+        context.AddVolume(ct.release());
+        context.AddVolume(pet.release());
 
-        context.AddInteractor(interactor.release());
-        context.SetCentralWidget(widget.release());
+        {
+          RenderStyle s;
+          //s.drawGrid_ = true;
+          s.alpha_ = 1;
+          widget->SetLayerStyle(0, s);
+        }
+
+        {
+          RenderStyle s;
+          //s.drawGrid_ = true;
+          s.SetColor(255, 0, 0);  // Draw missing PET layer in red
+          s.alpha_ = 0.5;
+          s.applyLut_ = true;
+          s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET;
+          s.interpolation_ = ImageInterpolation_Linear;
+          widget->SetLayerStyle(1, s);
+        }
+#endif
+
 
         statusBar.SetMessage("Use the keys \"b\", \"l\" and \"d\" to change Hounsfield windowing");
         statusBar.SetMessage("Use the keys \"t\" to track the (X,Y,Z) mouse coordinates");
         statusBar.SetMessage("Use the keys \"m\" to measure distances");
         statusBar.SetMessage("Use the keys \"c\" to draw circles");
+
+        widget->SetTransmitMouseOver(true);
+        widget->SetInteractor(context.AddInteractor(new Interactor(*this)));
+        context.SetCentralWidget(widget.release());
       }
     };
   }