changeset 121:e66b2c757790 wasm

displaying rt-struct
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 04 Oct 2017 17:53:47 +0200
parents 063f7f3d9f14
children e3433dabfb8d
files Applications/Samples/SingleFrameApplication.h Applications/Samples/SingleVolumeApplication.h Framework/Layers/DicomStructureSetRendererFactory.cpp Framework/Layers/DicomStructureSetRendererFactory.h Framework/Layers/ILayerSource.h Framework/Layers/LayerSourceBase.cpp Framework/Layers/LayerSourceBase.h Framework/Layers/OrthancFrameLayerSource.cpp Framework/Toolbox/DicomStructureSet.cpp Framework/Toolbox/OrthancSlicesLoader.cpp Framework/Toolbox/Slice.cpp Framework/Widgets/LayerWidget.cpp Framework/Widgets/LayerWidget.h Framework/dev.h Resources/CMake/OrthancStoneConfiguration.cmake UnitTestsSources/UnitTestsMain.cpp
diffstat 16 files changed, 122 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SingleFrameApplication.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Applications/Samples/SingleFrameApplication.h	Wed Oct 04 17:53:47 2017 +0200
@@ -197,7 +197,7 @@
  
       virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
                                     const ILayerSource& source,
-                                    const Slice& slice,
+                                    const CoordinateSystem3D& slice,
                                     bool isError)
       {
       }
--- a/Applications/Samples/SingleVolumeApplication.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Applications/Samples/SingleVolumeApplication.h	Wed Oct 04 17:53:47 2017 +0200
@@ -30,6 +30,9 @@
 #include <Core/Toolbox.h>
 #include <Core/Logging.h>
 
+#include <Plugins/Samples/Common/OrthancHttpConnection.h>   // TODO REMOVE
+#include "../../Framework/Layers/DicomStructureSetRendererFactory.h"   // TODO REMOVE
+
 namespace OrthancStone
 {
   namespace Samples
@@ -80,10 +83,13 @@
           widget_(widget),
           layer_(layer)
         {
-          printf("OOO\n");
         }
       };
 
+
+      std::auto_ptr<DicomStructureSet>  struct_;
+      
+
     public:
       virtual void DeclareCommandLineOptions(boost::program_options::options_description& options)
       {
@@ -170,7 +176,7 @@
 
         std::auto_ptr<LayerWidget> widget(new LayerWidget);
 
-#if 0
+#if 1
         std::auto_ptr<OrthancVolumeImage> volume(new OrthancVolumeImage(context.GetWebService(), true));
         if (series.empty())
         {
@@ -195,6 +201,12 @@
           widget->SetLayerStyle(0, s);
         }
 #else
+        {
+          OrthancPlugins::OrthancHttpConnection orthanc;
+          struct_.reset(new DicomStructureSet(orthanc, "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"));  // IBA
+          //struct_.reset(new DicomStructureSet(orthanc, "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"));  // 0522c0001 TCIA
+        }
+        
         std::auto_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context.GetWebService(), false));
         //ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d");
         ct->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa");  // IBA
@@ -209,9 +221,10 @@
 
         widget->AddLayer(new VolumeImageSource(*ct));
         widget->AddLayer(new VolumeImageSource(*pet));
+        widget->AddLayer(new DicomStructureSetRendererFactory(*struct_));
         
-        //context.AddInteractor(new Interactor(*pet, *widget, projection, 1));
-        context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection));
+        context.AddInteractor(new Interactor(*pet, *widget, projection, 1));
+        //context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection));
         context.AddVolume(ct.release());
         context.AddVolume(pet.release());
 
--- a/Framework/Layers/DicomStructureSetRendererFactory.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/DicomStructureSetRendererFactory.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -29,12 +29,12 @@
   {
   private:
     const DicomStructureSet&  structureSet_;
-    SliceGeometry             slice_;
+    CoordinateSystem3D        slice_;
     bool                      visible_;
 
   public:
     Renderer(const DicomStructureSet& structureSet,
-             const SliceGeometry& slice) :
+             const CoordinateSystem3D& slice) :
       structureSet_(structureSet),
       slice_(slice),
       visible_(true)
@@ -42,8 +42,7 @@
     }
 
     virtual bool RenderLayer(CairoContext& context,
-                             const ViewportGeometry& view,
-                             const SliceGeometry& viewportSlice)
+                             const ViewportGeometry& view)
     {
       if (visible_)
       {
@@ -54,6 +53,11 @@
       return true;
     }
 
+    virtual const CoordinateSystem3D& GetLayerSlice()
+    {
+      return slice_;
+    }
+
     virtual void SetLayerStyle(const RenderStyle& style)
     {
       visible_ = style.visible_;
@@ -66,22 +70,12 @@
   };
 
 
-  ILayerRenderer* DicomStructureSetRendererFactory::CreateLayerRenderer(const SliceGeometry& displaySlice)
+  void DicomStructureSetRendererFactory::ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice)
   {
     bool isOpposite;
-    if (GeometryToolbox::IsParallelOrOpposite(isOpposite, displaySlice.GetNormal(), structureSet_.GetNormal()))
+    if (GeometryToolbox::IsParallelOrOpposite(isOpposite, viewportSlice.GetNormal(), structureSet_.GetNormal()))
     {
-      return new Renderer(structureSet_, displaySlice);
-    }
-    else
-    {
-      return NULL;
+      NotifyLayerReady(new Renderer(structureSet_, viewportSlice), viewportSlice, false);
     }
   }
-
-
-  ISliceableVolume& DicomStructureSetRendererFactory::GetSourceVolume() const
-  {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-  }
 }
--- a/Framework/Layers/DicomStructureSetRendererFactory.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/DicomStructureSetRendererFactory.h	Wed Oct 04 17:53:47 2017 +0200
@@ -22,11 +22,11 @@
 #pragma once
 
 #include "../Toolbox/DicomStructureSet.h"
-#include "ILayerRendererFactory.h"
+#include "LayerSourceBase.h"
 
 namespace OrthancStone
 {
-  class DicomStructureSetRendererFactory : public ILayerRendererFactory
+  class DicomStructureSetRendererFactory : public LayerSourceBase
   {
   private:
     class Renderer;
@@ -34,27 +34,17 @@
     const DicomStructureSet&  structureSet_;
 
   public:
-    DicomStructureSetRendererFactory(const DicomStructureSet&  structureSet) :
+    DicomStructureSetRendererFactory(const DicomStructureSet& structureSet) :
       structureSet_(structureSet)
     {
     }
 
-    virtual bool GetExtent(double& x1,
-                           double& y1,
-                           double& x2,
-                           double& y2,
-                           const SliceGeometry& displaySlice)
+    virtual bool GetExtent(std::vector<Vector>& points,
+                           const CoordinateSystem3D& viewportSlice)
     {
       return false;
     }
 
-    virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& displaySlice);
-
-    virtual bool HasSourceVolume() const
-    {
-      return false;
-    }
-
-    virtual ISliceableVolume& GetSourceVolume() const;
+    virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice);
   };
 }
--- a/Framework/Layers/ILayerSource.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/ILayerSource.h	Wed Oct 04 17:53:47 2017 +0200
@@ -55,7 +55,7 @@
       // std::auto_ptr
       virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
                                     const ILayerSource& source,
-                                    const Slice& slice,  // TODO Shouldn't this be CoordinateSystem3D? Is it necessary given ILayerS::GetLayerSlice()?
+                                    const CoordinateSystem3D& slice,
                                     bool isError) = 0;  // TODO Shouldn't this be separate as NotifyLayerError?
     };
     
--- a/Framework/Layers/LayerSourceBase.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/LayerSourceBase.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -31,12 +31,12 @@
     {
     private:
       std::auto_ptr<ILayerRenderer>  layer_;
-      const Slice&                   slice_;
+      const CoordinateSystem3D&      slice_;
       bool                           isError_;
       
     public:
       LayerReadyFunctor(ILayerRenderer* layer,
-                        const Slice& slice,
+                        const CoordinateSystem3D& slice,
                         bool isError) :
         layer_(layer),
         slice_(slice),
@@ -73,7 +73,7 @@
   }
 
   void LayerSourceBase::NotifyLayerReady(ILayerRenderer* layer,
-                                         const Slice& slice,
+                                         const CoordinateSystem3D& slice,
                                          bool isError)
   {
     LayerReadyFunctor functor(layer, slice, isError);
--- a/Framework/Layers/LayerSourceBase.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/LayerSourceBase.h	Wed Oct 04 17:53:47 2017 +0200
@@ -43,7 +43,7 @@
     void NotifySliceChange(const Slice& slice);
 
     void NotifyLayerReady(ILayerRenderer* layer,
-                          const Slice& slice,
+                          const CoordinateSystem3D& slice,
                           bool isError);
 
   public:
--- a/Framework/Layers/OrthancFrameLayerSource.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Layers/OrthancFrameLayerSource.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -56,7 +56,7 @@
   {
     bool isFull = (quality == SliceImageQuality_Full);
     LayerSourceBase::NotifyLayerReady(FrameRenderer::CreateRenderer(image.release(), slice, isFull),
-                                      slice, false);
+                                      slice.GetGeometry(), false);
   }
 
   void OrthancFrameLayerSource::NotifySliceImageError(const OrthancSlicesLoader& loader,
@@ -64,7 +64,7 @@
                                                       const Slice& slice,
                                                       SliceImageQuality quality)
   {
-    LayerSourceBase::NotifyLayerReady(NULL, slice, true);
+    LayerSourceBase::NotifyLayerReady(NULL, slice.GetGeometry(), true);
   }
 
 
@@ -124,7 +124,7 @@
       else
       {
         Slice slice;
-        LayerSourceBase::NotifyLayerReady(NULL, slice, true);
+        LayerSourceBase::NotifyLayerReady(NULL, slice.GetGeometry(), true);
       }
     }
   }
--- a/Framework/Toolbox/DicomStructureSet.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Toolbox/DicomStructureSet.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -232,7 +232,7 @@
       if (!tags.GetSequenceSize(countSlices, DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
                                                        DICOM_TAG_CONTOUR_SEQUENCE)))
       {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
+        countSlices = 0;
       }
 
       LOG(WARNING) << "New RT structure: \"" << structures_[i].name_ 
@@ -253,7 +253,7 @@
           throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
         }
             
-        LOG(INFO) << "Parsing slice containing " << countPoints << " vertices";
+        //LOG(INFO) << "Parsing slice containing " << countPoints << " vertices";
 
         std::string type = reader.GetMandatoryStringValue(DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i,
                                                                     DICOM_TAG_CONTOUR_SEQUENCE, j,
@@ -371,6 +371,19 @@
     for (Structures::const_iterator structure = structures_.begin();
          structure != structures_.end(); ++structure)
     {
+      if (structure->name_ != "SKIN" &&
+          structure->name_ != "HEART" &&
+          //structure->name_ != "CORD" &&
+          structure->name_ != "ESOPHAGUS" &&
+          structure->name_ != "LUNG_LT" &&
+          structure->name_ != "LUNG_RT" &&
+          structure->name_ != "GTV_EXH_PRIMARY" &&
+          structure->name_ != "GTV_INH_PRIMARY" &&
+          structure->name_ != "GTV_PRIMARY")
+      {
+        continue;
+      }
+      
       for (Polygons::const_iterator polygon = structure->polygons_.begin();
            polygon != structure->polygons_.end(); ++polygon)
       {
@@ -394,10 +407,10 @@
 
           slice.ProjectPoint(x, y, *polygon->points_.begin());
           cairo_line_to(cr, x, y);
+
+          cairo_stroke(cr);
         }
       }
     }
-
-    cairo_stroke(cr);
   }
 }
--- a/Framework/Toolbox/OrthancSlicesLoader.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Toolbox/OrthancSlicesLoader.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -659,7 +659,6 @@
     compressor.Uncompress(raw, answer, size);
     
     const Orthanc::DicomImageInformation& info = operation.GetSlice().GetImageInformation();
-    unsigned int frame = operation.GetSlice().GetFrame();
     
     if (info.GetBitsAllocated() == 32 &&
         info.GetBitsStored() == 32 &&
--- a/Framework/Toolbox/Slice.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Toolbox/Slice.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -104,9 +104,6 @@
       thickness_ = -thickness_;
     }
 
-    printf("%d: %f %f %f\n", frame_, geometry_.GetOrigin()[0], geometry_.GetOrigin()[1], geometry_.GetOrigin()[2]);
-    //printf("%f %f %f\n", pixelSpacingX_, pixelSpacingY_, thickness_);
-    
     return true;
   }
 
--- a/Framework/Widgets/LayerWidget.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Widgets/LayerWidget.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -33,6 +33,7 @@
   {
   private:
     CoordinateSystem3D            slice_;
+    double                        thickness_;
     size_t                        countMissing_;
     std::vector<ILayerRenderer*>  renderers_;
 
@@ -56,11 +57,17 @@
       
   public:
     Scene(const CoordinateSystem3D& slice,
+          double thickness,
           size_t countLayers) :
       slice_(slice),
+      thickness_(thickness),
       countMissing_(countLayers),
       renderers_(countLayers, NULL)
     {
+      if (thickness <= 0)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+      }
     }
 
     ~Scene()
@@ -193,6 +200,34 @@
         renderers_[index]->SetLayerStyle(style);
       }
     }
+
+    bool ContainsPlane(const CoordinateSystem3D& slice) const
+    {
+      bool isOpposite;
+      if (!GeometryToolbox::IsParallelOrOpposite(isOpposite,
+                                                 slice.GetNormal(),
+                                                 slice_.GetNormal()))
+      {
+        return false;
+      }
+      else
+      {
+        double z = (slice_.ProjectAlongNormal(slice.GetOrigin()) -
+                    slice_.ProjectAlongNormal(slice_.GetOrigin()));
+      
+        if (z < 0)
+        {
+          z = -z;
+        }
+
+        return z <= thickness_;
+      }
+    }
+
+    double GetThickness() const
+    {
+      return thickness_;
+    }
   };
 
   
@@ -266,13 +301,23 @@
   
   void LayerWidget::ResetPendingScene()
   {
-    pendingScene_.reset(new Scene(slice_, layers_.size()));
+    double thickness;
+    if (pendingScene_.get() == NULL)
+    {
+      thickness = 1.0;
+    }
+    else
+    {
+      thickness = pendingScene_->GetThickness();
+    }
+    
+    pendingScene_.reset(new Scene(slice_, thickness, layers_.size()));
   }
   
 
   void LayerWidget::UpdateLayer(size_t index,
                                 ILayerRenderer* renderer,
-                                const Slice& slice)
+                                const CoordinateSystem3D& slice)
   {
     LOG(INFO) << "Updating layer " << index;
     
@@ -292,13 +337,13 @@
     renderer->SetLayerStyle(styles_[index]);
 
     if (currentScene_.get() != NULL &&
-        slice.ContainsPlane(currentScene_->GetSlice()))
+        currentScene_->ContainsPlane(slice))
     {
       currentScene_->SetLayer(index, tmp.release());
       NotifyChange();
     }
     else if (pendingScene_.get() != NULL &&
-             slice.ContainsPlane(pendingScene_->GetSlice()))
+             pendingScene_->ContainsPlane(slice))
     {
       pendingScene_->SetLayer(index, tmp.release());
 
@@ -483,13 +528,11 @@
   
   void LayerWidget::NotifyLayerReady(std::auto_ptr<ILayerRenderer>& renderer,
                                      const ILayerSource& source,
-                                     const Slice& slice,
+                                     const CoordinateSystem3D& slice,
                                      bool isError)
   {
     size_t index;
-    if (slice.IsValid() &&
-        LookupLayer(index, source) &&
-        slice.ContainsPlane(slice_))  // Whether the slice comes from an older request
+    if (LookupLayer(index, source))
     {
       if (isError)
       {
@@ -506,7 +549,8 @@
       }
       else if (isError)
       {
-        UpdateLayer(index, new SliceOutlineRenderer(slice), slice);
+        // TODO
+        //UpdateLayer(index, new SliceOutlineRenderer(slice), slice);
       }
     }
   }
--- a/Framework/Widgets/LayerWidget.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/Widgets/LayerWidget.h	Wed Oct 04 17:53:47 2017 +0200
@@ -64,7 +64,7 @@
 
     virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& renderer,
                                   const ILayerSource& source,
-                                  const Slice& slice,
+                                  const CoordinateSystem3D& slice,
                                   bool isError);
 
     void ResetChangedLayers();
@@ -80,7 +80,7 @@
 
     void UpdateLayer(size_t index,
                      ILayerRenderer* renderer,
-                     const Slice& slice);
+                     const CoordinateSystem3D& slice);
 
     void InvalidateAllLayers();
 
--- a/Framework/dev.h	Wed Oct 04 15:51:34 2017 +0200
+++ b/Framework/dev.h	Wed Oct 04 17:53:47 2017 +0200
@@ -615,13 +615,13 @@
           LayerSourceBase::NotifyLayerReady(
             FrameRenderer::CreateRenderer(frame.release(), *slice, isFullQuality),
             //new SliceOutlineRenderer(slice),
-            *slice, false);
+            slice->GetGeometry(), false);
           return;
         }
       }
 
       // Error
-      Slice slice;
+      CoordinateSystem3D slice;
       LayerSourceBase::NotifyLayerReady(NULL, slice, true);
     }
   };
@@ -819,7 +819,7 @@
                                                viewportSlice.GetOrigin(), viewportSlice.GetNormal()))
       {
         // The two slice are parallel, don't try and display the intersection
-        NotifyLayerReady(NULL, reference, false);
+        NotifyLayerReady(NULL, reference.GetGeometry(), false);
       }
       else
       {
@@ -834,12 +834,12 @@
                                                  extent.GetX1(), extent.GetY1(),
                                                  extent.GetX2(), extent.GetY2()))
         {
-          NotifyLayerReady(new LineLayerRenderer(x1, y1, x2, y2, slice), reference, false);
+          NotifyLayerReady(new LineLayerRenderer(x1, y1, x2, y2, slice), reference.GetGeometry(), false);
         }
         else
         {
           // Parallel slices
-          NotifyLayerReady(NULL, reference, false);
+          NotifyLayerReady(NULL, reference.GetGeometry(), false);
         }
       }
     }      
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Oct 04 15:51:34 2017 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Oct 04 17:53:47 2017 +0200
@@ -160,13 +160,13 @@
 endif()
 
 list(APPEND ORTHANC_STONE_SOURCES
-  #${ORTHANC_STONE_DIR}/Framework/Layers/DicomStructureSetRendererFactory.cpp
   #${ORTHANC_STONE_DIR}/Framework/Layers/SeriesFrameRendererFactory.cpp
   #${ORTHANC_STONE_DIR}/Framework/Layers/SiblingSliceLocationFactory.cpp
   #${ORTHANC_STONE_DIR}/Framework/Layers/SingleFrameRendererFactory.cpp
   ${ORTHANC_STONE_DIR}/Framework/Enumerations.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/CircleMeasureTracker.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/ColorFrameRenderer.cpp
+  ${ORTHANC_STONE_DIR}/Framework/Layers/DicomStructureSetRendererFactory.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/FrameRenderer.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/GrayscaleFrameRenderer.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/LayerSourceBase.cpp
--- a/UnitTestsSources/UnitTestsMain.cpp	Wed Oct 04 15:51:34 2017 +0200
+++ b/UnitTestsSources/UnitTestsMain.cpp	Wed Oct 04 17:53:47 2017 +0200
@@ -117,7 +117,7 @@
 
   Orthanc::WebServiceParameters web;
   OrthancStone::OracleWebService orthanc(oracle, web);
-  OrthancStone::OrthancVolumeImage volume(orthanc);
+  OrthancStone::OrthancVolumeImage volume(orthanc, true);
 
   //volume.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0);
   //volume.ScheduleLoadSeries("318603c5-03e8cffc-a82b6ee1-3ccd3c1e-18d7e3bb"); // COMUNIX PET