changeset 107:71d574a3607f wasm

removing unused files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 14 Jun 2017 15:07:07 +0200
parents 6a7c702a7531
children 37d4ae7052a5
files Applications/BasicApplicationContext.cpp Framework/Layers/ILayerRendererFactory.h Framework/Volumes/VolumeImage.cpp Framework/Volumes/VolumeImage.h Framework/Volumes/VolumeImagePolicyBase.cpp Framework/Volumes/VolumeImagePolicyBase.h Framework/Volumes/VolumeImageProgressivePolicy.cpp Framework/Volumes/VolumeImageProgressivePolicy.h Framework/Volumes/VolumeImageSimplePolicy.cpp Framework/Volumes/VolumeImageSimplePolicy.h Framework/Widgets/LayeredSceneWidget.cpp Framework/Widgets/LayeredSceneWidget.h Resources/CMake/OrthancStone.cmake
diffstat 13 files changed, 0 insertions(+), 1855 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/BasicApplicationContext.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ b/Applications/BasicApplicationContext.cpp	Wed Jun 14 15:07:07 2017 +0200
@@ -22,8 +22,6 @@
 #include "BasicApplicationContext.h"
 
 #include "../../Framework/Toolbox/OrthancSeriesLoader.h"
-#include "../../Framework/Volumes/VolumeImageSimplePolicy.h"
-#include "../../Framework/Volumes/VolumeImageProgressivePolicy.h"
 
 namespace OrthancStone
 {
--- a/Framework/Layers/ILayerRendererFactory.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "ILayerRenderer.h"
-#include "../Toolbox/SliceGeometry.h"
-#include "../Volumes/ISliceableVolume.h"
-
-namespace OrthancStone
-{
-  class ILayerRendererFactory : public boost::noncopyable
-  {
-  public:
-    virtual ~ILayerRendererFactory()
-    {
-    }
-
-    virtual bool GetExtent(double& x1,
-                           double& y1,
-                           double& x2,
-                           double& y2,
-                           const SliceGeometry& displaySlice) = 0;
-
-    // This operation can be slow, as it might imply the download of a
-    // slice from Orthanc. The result might be NULL, if the slice is
-    // not compatible with the underlying source volume.
-    virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& displaySlice) = 0;
-
-    virtual bool HasSourceVolume() const = 0;
-
-    virtual ISliceableVolume& GetSourceVolume() const = 0;
-  };
-}
--- a/Framework/Volumes/VolumeImage.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,400 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "VolumeImage.h"
-
-#include "../../Resources/Orthanc/Core/Logging.h"
-#include "../Layers/FrameRenderer.h"
-
-namespace OrthancStone
-{
-  void VolumeImage::StoreUpdateTime()
-  {
-    lastUpdate_ = MessagingToolbox::Timestamp();
-  }
-
-
-  void VolumeImage::NotifyChange(bool force)
-  {
-    bool go = false;
-
-    if (force)
-    {
-      go = true;
-    }
-    else
-    {
-      // Don't notify the observers more than 5 times per second
-      MessagingToolbox::Timestamp now;
-      go = (now.GetMillisecondsSince(lastUpdate_) > 200);
-    }
-
-    if (go)
-    {
-      StoreUpdateTime();
-      observers_.NotifyChange(this);
-    }
-  }
-
-
-  void VolumeImage::LoadThread(VolumeImage* that)
-  {
-    while (that->continue_)
-    {
-      bool complete = false;
-      bool done = that->policy_->DownloadStep(complete);
-
-      if (complete)
-      {
-        that->loadingComplete_ = true;
-      }
-
-      if (done)
-      {
-        break;
-      }
-      else
-      {
-        that->NotifyChange(false);
-      }
-    }
-
-    that->NotifyChange(true);
-  }
-
-
-  VolumeImage::VolumeImage(ISeriesLoader* loader) :   // Takes ownership
-    loader_(loader),
-    threads_(1),
-    started_(false),
-    continue_(false),
-    loadingComplete_(false)
-  {
-    if (loader == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-    }
-
-    const size_t depth = loader_->GetGeometry().GetSliceCount();
-      
-    if (depth < 2)
-    {
-      // Empty or flat series
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat);
-    }
-
-    // TODO Check pixel spacing, slice thickness, and windowing are
-    // constant across slices
-    referenceDataset_.reset(loader->DownloadDicom(0));
-
-    double spacingZ;
-
-    {
-      // Project the origin of the first and last slices onto the normal
-      const SliceGeometry& s1 = loader_->GetGeometry().GetSlice(0);
-      const SliceGeometry& s2 = loader_->GetGeometry().GetSlice(depth - 1);
-      const Vector& normal = loader_->GetGeometry().GetNormal();
-
-      double p1 = boost::numeric::ublas::inner_prod(s1.GetOrigin(), normal);
-      double p2 = boost::numeric::ublas::inner_prod(s2.GetOrigin(), normal);
-
-      spacingZ = fabs(p2 - p1) / static_cast<double>(depth);
-
-      // TODO Check that all slices are evenly distributed
-    }      
-
-    buffer_.reset(new ImageBuffer3D(loader_->GetPixelFormat(), 
-                                    loader_->GetWidth(), 
-                                    loader_->GetHeight(),
-                                    depth));
-    buffer_->Clear();
-    buffer_->SetAxialGeometry(loader_->GetGeometry().GetSlice(0));
-
-    double spacingX, spacingY;
-    GeometryToolbox::GetPixelSpacing(spacingX, spacingY, *referenceDataset_);
-    buffer_->SetVoxelDimensions(spacingX, spacingY, spacingZ);
-
-    // These 3 values are only used to speed up the LayerFactory
-    axialGeometry_.reset(buffer_->GetGeometry(VolumeProjection_Axial));
-    coronalGeometry_.reset(buffer_->GetGeometry(VolumeProjection_Coronal));
-    sagittalGeometry_.reset(buffer_->GetGeometry(VolumeProjection_Sagittal));
-  }
-
-
-  VolumeImage::~VolumeImage()
-  {
-    Stop();
-      
-    for (size_t i = 0; i < threads_.size(); i++)
-    {
-      if (threads_[i] != NULL)
-      {
-        delete threads_[i];
-      }
-    }
-  }
-
-
-  void VolumeImage::SetDownloadPolicy(IDownloadPolicy* policy)   // Takes ownership
-  {
-    if (started_)
-    {
-      LOG(ERROR) << "Cannot change the number of threads after a call to Start()";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    policy_.reset(policy);
-  }
-
-
-  void VolumeImage::SetThreadCount(size_t count)
-  {
-    if (started_)
-    {
-      LOG(ERROR) << "Cannot change the number of threads after a call to Start()";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    if (count <= 0)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    threads_.resize(count);
-  }
-
-
-  void VolumeImage::Register(IObserver& observer)
-  {
-    observers_.Register(observer);
-  }
-
-
-  void VolumeImage::Unregister(IObserver& observer)
-  {
-    observers_.Unregister(observer);
-  }
-
-
-  void VolumeImage::Start()
-  {
-    if (started_)
-    {
-      LOG(ERROR) << "Cannot call Start() twice";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    started_ = true;
-    StoreUpdateTime();
-
-    if (policy_.get() != NULL &&
-        threads_.size() > 0)
-    {
-      continue_ = true;
-      policy_->Initialize(*buffer_, *loader_);
-
-      for (size_t i = 0; i < threads_.size(); i++)
-      {
-        assert(threads_[i] == NULL);
-        threads_[i] = new boost::thread(LoadThread, this);
-      }
-    }
-  }
-
-
-  void VolumeImage::Stop()
-  {
-    if (!started_)
-    {
-      LOG(ERROR) << "Cannot call Stop() without calling Start() beforehand";
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    if (continue_)
-    {
-      continue_ = false;
-
-      for (size_t i = 0; i < threads_.size(); i++)
-      {
-        if (threads_[i]->joinable())
-        {
-          threads_[i]->join();
-        }
-      }
-
-      assert(policy_.get() != NULL);
-      policy_->Finalize();
-    }
-  }
-
-
-  ParallelSlices* VolumeImage::GetGeometry(VolumeProjection projection,
-                                           bool reverse)
-  {
-    std::auto_ptr<ParallelSlices> slices(buffer_->GetGeometry(projection));
-
-    if (reverse)
-    {
-      return slices->Reverse();
-    }
-    else
-    {
-      return slices.release();
-    }
-  }
-
-
-  bool VolumeImage::DetectProjection(VolumeProjection& projection,
-                                     bool& reverse,
-                                     const SliceGeometry& viewportSlice)
-  {
-    if (GeometryToolbox::IsParallelOrOpposite(reverse, viewportSlice.GetNormal(), axialGeometry_->GetNormal()))
-    {
-      projection = VolumeProjection_Axial;
-      return true;
-    }
-    else if (GeometryToolbox::IsParallelOrOpposite(reverse, viewportSlice.GetNormal(), sagittalGeometry_->GetNormal()))
-    {
-      projection = VolumeProjection_Sagittal;
-      return true;
-    }
-    else if (GeometryToolbox::IsParallelOrOpposite(reverse, viewportSlice.GetNormal(), coronalGeometry_->GetNormal()))
-    {
-      projection = VolumeProjection_Coronal;
-      return true;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-  const ParallelSlices& VolumeImage::GetGeometryInternal(VolumeProjection projection)
-  {
-    switch (projection)
-    {
-      case VolumeProjection_Axial:
-        return *axialGeometry_;
-
-      case VolumeProjection_Sagittal:
-        return *sagittalGeometry_;
-
-      case VolumeProjection_Coronal:
-        return *coronalGeometry_;
-
-      default:
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-  }
-
-
-  bool VolumeImage::LayerFactory::GetExtent(double& x1,
-                                            double& y1,
-                                            double& x2,
-                                            double& y2,
-                                            const SliceGeometry& viewportSlice)
-  {
-    VolumeProjection projection;
-    bool reverse;
-
-    if (that_.buffer_->GetWidth() == 0 ||
-        that_.buffer_->GetHeight() == 0 ||
-        that_.buffer_->GetDepth() == 0 ||
-        !that_.DetectProjection(projection, reverse, viewportSlice))
-    {
-      return false;
-    }
-    else
-    {
-      Vector spacing = that_.GetVoxelDimensions(projection);
-
-      unsigned int width, height;
-      that_.buffer_->GetSliceSize(width, height, projection);
-
-      // As the slices of the volumic image are arranged in a box,
-      // we only consider one single reference slice (the one with index 0).
-      const SliceGeometry& volumeSlice = that_.GetGeometryInternal(projection).GetSlice(0);
-
-      return FrameRenderer::ComputeFrameExtent(x1, y1, x2, y2, 
-                                               viewportSlice, volumeSlice,
-                                               width, height,
-                                               spacing[0], spacing[1]);
-    }
-  }
-
-
-  ILayerRenderer* VolumeImage::LayerFactory::CreateLayerRenderer(const SliceGeometry& viewportSlice)
-  {
-    VolumeProjection projection;
-    bool reverse;
-    
-    if (that_.buffer_->GetWidth() == 0 ||
-        that_.buffer_->GetHeight() == 0 ||
-        that_.buffer_->GetDepth() == 0 ||
-        !that_.DetectProjection(projection, reverse, viewportSlice))
-    {
-      return NULL;
-    }
-
-    const ParallelSlices& geometry = that_.GetGeometryInternal(projection);
-
-    size_t closest;
-    double distance;
-
-    const Vector spacing = that_.GetVoxelDimensions(projection);
-    const double sliceThickness = spacing[2];
-
-    if (geometry.ComputeClosestSlice(closest, distance, viewportSlice.GetOrigin()) &&
-        distance <= sliceThickness / 2.0)
-    {
-      bool isFullQuality;
-
-      if (projection == VolumeProjection_Axial &&
-          that_.policy_.get() != NULL)
-      {
-        isFullQuality = that_.policy_->IsFullQualityAxial(closest);
-      }
-      else
-      {
-        isFullQuality = that_.IsLoadingComplete();
-      }
-
-      std::auto_ptr<Orthanc::Image> frame;
-      SliceGeometry frameSlice = geometry.GetSlice(closest);
-
-      {
-        ImageBuffer3D::SliceReader reader(*that_.buffer_, projection, closest);
-        frame.reset(Orthanc::Image::Clone(reader.GetAccessor()));
-      }
-
-      return FrameRenderer::CreateRenderer(frame.release(), 
-                                           frameSlice, 
-                                           *that_.referenceDataset_, 
-                                           spacing[0], spacing[1],
-                                           isFullQuality);
-    }
-    else
-    {
-      return NULL;
-    }
-  }
-}
--- a/Framework/Volumes/VolumeImage.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "ISliceableVolume.h"
-#include "ImageBuffer3D.h"
-#include "../Toolbox/ISeriesLoader.h"
-#include "../Toolbox/MessagingToolbox.h"
-#include "../Toolbox/ObserversRegistry.h"
-#include "../Layers/ILayerRendererFactory.h"
-
-#include <boost/thread.hpp>
-
-namespace OrthancStone
-{
-  class VolumeImage : public ISliceableVolume
-  {
-  public:
-    class IDownloadPolicy : public boost::noncopyable
-    {
-    public:
-      virtual ~IDownloadPolicy()
-      {
-      }
-      
-      virtual void Initialize(ImageBuffer3D& buffer,
-                              ISeriesLoader& loader) = 0;
-
-      virtual void Finalize() = 0;
-
-      // Must return "true" if the thread has completed its task. Pay
-      // attention that this method can be invoked concurrently by
-      // several download threads.
-      virtual bool DownloadStep(bool& complete) = 0;
-
-      virtual bool IsFullQualityAxial(size_t slice) = 0;
-    };
-
-
-  private:
-    std::auto_ptr<ISeriesLoader>                  loader_;
-    std::auto_ptr<ImageBuffer3D>                  buffer_;
-    std::vector<boost::thread*>                   threads_;
-    bool                                          started_;
-    bool                                          continue_;
-    ObserversRegistry<ISliceableVolume>           observers_;
-    bool                                          loadingComplete_;
-    MessagingToolbox::Timestamp                   lastUpdate_;
-    std::auto_ptr<OrthancPlugins::IDicomDataset>  referenceDataset_;
-    std::auto_ptr<IDownloadPolicy>                policy_;
-    
-    std::auto_ptr<ParallelSlices>        axialGeometry_;
-    std::auto_ptr<ParallelSlices>        coronalGeometry_;
-    std::auto_ptr<ParallelSlices>        sagittalGeometry_;
-
-    void StoreUpdateTime();
-
-    void NotifyChange(bool force);
-
-    static void LoadThread(VolumeImage* that);
-
-    bool DetectProjection(VolumeProjection& projection,
-                          bool& reverse,
-                          const SliceGeometry& viewportSlice);
-
-    const ParallelSlices& GetGeometryInternal(VolumeProjection projection);
-
-  public:
-    VolumeImage(ISeriesLoader* loader);   // Takes ownership
-
-    virtual ~VolumeImage();
-
-    void SetDownloadPolicy(IDownloadPolicy* policy);   // Takes ownership
-
-    void SetThreadCount(size_t count);
-
-    size_t GetThreadCount() const
-    {
-      return threads_.size();
-    }
-
-    virtual void Register(IObserver& observer);
-
-    virtual void Unregister(IObserver& observer);
-
-    virtual void Start();
-
-    virtual void Stop();
-
-    ParallelSlices* GetGeometry(VolumeProjection projection,
-                                bool reverse);
-
-    Vector GetVoxelDimensions(VolumeProjection projection)
-    {
-      return buffer_->GetVoxelDimensions(projection);
-    }
-
-    bool IsLoadingComplete() const
-    {
-      return loadingComplete_;
-    }
-
-    class LayerFactory : public ILayerRendererFactory
-    {
-    private:
-      VolumeImage&  that_;
-
-    public:
-      LayerFactory(VolumeImage& that) :
-        that_(that)
-      {
-      }
-
-      virtual bool HasSourceVolume() const
-      {
-        return true;
-      }
-
-      virtual ISliceableVolume& GetSourceVolume() const
-      {
-        return that_;
-      }
-
-      virtual bool GetExtent(double& x1,
-                             double& y1,
-                             double& x2,
-                             double& y2,
-                             const SliceGeometry& viewportSlice);
-
-      virtual ILayerRenderer* CreateLayerRenderer(const SliceGeometry& viewportSlice);    
-    };
-  };
-}
--- a/Framework/Volumes/VolumeImagePolicyBase.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "VolumeImagePolicyBase.h"
-
-namespace OrthancStone
-{
-  VolumeImagePolicyBase::VolumeImagePolicyBase() : 
-    buffer_(NULL),
-    loader_(NULL)
-  {
-  }
-
-
-  void VolumeImagePolicyBase::Initialize(ImageBuffer3D& buffer,
-                                         ISeriesLoader& loader)
-  {
-    if (buffer_ != NULL ||
-        loader_ != NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-
-    buffer_ = &buffer;
-    loader_ = &loader;
-
-    InitializeInternal(buffer, loader);
-  }
-
-
-  bool VolumeImagePolicyBase::DownloadStep(bool& complete)
-  {
-    if (buffer_ == NULL ||
-        loader_ == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-    else
-    {
-      return DownloadStepInternal(complete, *buffer_, *loader_);                                    
-    }
-  }
-}
--- a/Framework/Volumes/VolumeImagePolicyBase.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "VolumeImage.h"
-
-namespace OrthancStone
-{
-  class VolumeImagePolicyBase : public VolumeImage::IDownloadPolicy
-  {
-  private:
-    ImageBuffer3D*  buffer_;
-    ISeriesLoader*  loader_;
-
-  protected:
-    virtual void InitializeInternal(ImageBuffer3D& buffer,
-                                    ISeriesLoader& loader) = 0;
-
-    virtual bool DownloadStepInternal(bool& complete,
-                                      ImageBuffer3D& buffer,
-                                      ISeriesLoader& loader) = 0;
-
-  public:
-    VolumeImagePolicyBase();
-
-    virtual void Initialize(ImageBuffer3D& buffer,
-                            ISeriesLoader& loader);
-
-    virtual void Finalize()
-    {
-    }
-
-    virtual bool DownloadStep(bool& complete);
-  };
-}
--- a/Framework/Volumes/VolumeImageProgressivePolicy.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "VolumeImageProgressivePolicy.h"
-
-#include "../Toolbox/DownloadStack.h"
-#include "../../Resources/Orthanc/Core/Images/ImageProcessing.h"
-
-namespace OrthancStone
-{
-  class VolumeImageProgressivePolicy::AxialSlicesScheduler
-  {
-  private:
-    size_t         depth_;
-    DownloadStack  stack_;
-
-  public:
-    AxialSlicesScheduler(size_t depth) :
-      depth_(depth),
-      stack_(3 * depth)    // "3" stands for the number of quality levels
-    {
-      assert(depth > 0);
-    }
-
-    void TagFullPriority(int z,
-                         int neighborhood)
-    {
-      DownloadStack::Writer writer(stack_);
-
-      // Also schedule the neighboring slices for download in medium quality
-      for (int offset = neighborhood; offset >= 1; offset--)
-      {
-        writer.SetTopNodePermissive((z + offset) + depth_ * Quality_Medium);
-        writer.SetTopNodePermissive((z - offset) + depth_ * Quality_Medium);
-      }
-
-      writer.SetTopNodePermissive(z + depth_ * Quality_Full);
-    }
-
-    bool LookupSlice(unsigned int& z,
-                     Quality& quality)
-    {
-      unsigned int value;
-      if (stack_.Pop(value))
-      {
-        z = value % depth_;
-
-        switch (value / depth_)
-        {
-          case 0:
-            quality = Quality_Low;
-            break;
-
-          case 1:
-            quality = Quality_Medium;
-            break;
-
-          case 2:
-            quality = Quality_Full;
-            break;
-
-          default:
-            throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-        }
-
-        return true;
-      }
-      else
-      {
-        return false;
-      }
-    }
-  };
-
-
-  bool VolumeImageProgressivePolicy::IsComplete()
-  {
-    boost::mutex::scoped_lock lock(qualityMutex_);
-        
-    for (size_t i = 0; i < axialSlicesQuality_.size(); i++)
-    {
-      if (axialSlicesQuality_[i] != Quality_Full)
-      {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-
-  void VolumeImageProgressivePolicy::InitializeInternal(ImageBuffer3D& buffer,
-                                                        ISeriesLoader& loader)
-  {
-    const size_t depth = loader.GetGeometry().GetSliceCount();
-
-    isJpegAvailable_ = loader.IsJpegAvailable();
-
-    axialSlicesQuality_.clear();
-    axialSlicesQuality_.resize(depth, Quality_None);
-    scheduler_.reset(new AxialSlicesScheduler(depth));
-  }
-
-
-  bool VolumeImageProgressivePolicy::DownloadStepInternal(bool& complete,
-                                                          ImageBuffer3D& buffer,
-                                                          ISeriesLoader& loader)
-  {
-    unsigned int z;
-    Quality quality;
-
-    if (!scheduler_->LookupSlice(z, quality))
-    {
-      // There is no more frame to be downloaded. Before stopping,
-      // each loader thread checks whether all the frames have been
-      // downloaded at maximum quality.
-      complete = IsComplete();
-      return true;
-    }
-
-    if (quality != Quality_Full &&
-        !isJpegAvailable_)
-    {
-      // Cannot fulfill this command, as progressive JPEG download
-      // is unavailable (i.e. the Web viewer plugin is unavailable)
-      return false;
-    }
-
-    std::auto_ptr<Orthanc::ImageAccessor> frame;
-
-    try
-    {
-      switch (quality)
-      {
-        case Quality_Low:
-          frame.reset(loader.DownloadJpegFrame(z, 10));
-          break;
-
-        case Quality_Medium:
-          frame.reset(loader.DownloadJpegFrame(z, 90));
-          break;
-
-        case Quality_Full:
-          frame.reset(loader.DownloadFrame(z));
-          break;
-
-        default:
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-    }
-    catch (Orthanc::OrthancException&)
-    {
-      // The Orthanc server cannot decode this instance
-      return false;
-    }
-
-    if (frame.get() != NULL)
-    {
-      boost::mutex::scoped_lock lock(qualityMutex_);
-
-      if (axialSlicesQuality_[z] == Quality_None ||
-          axialSlicesQuality_[z] < quality)
-      {
-        axialSlicesQuality_[z] = quality;
-
-        ImageBuffer3D::SliceWriter writer(buffer, VolumeProjection_Axial, z);
-        Orthanc::ImageProcessing::Convert(writer.GetAccessor(), *frame);
-      }
-    }
-
-    return false;
-  }
-
-
-  bool VolumeImageProgressivePolicy::IsFullQualityAxial(size_t slice)
-  {
-    scheduler_->TagFullPriority(slice, 3);
-
-    {
-      boost::mutex::scoped_lock lock(qualityMutex_);
-      return (axialSlicesQuality_[slice] == Quality_Full);
-    }
-  }
-}
--- a/Framework/Volumes/VolumeImageProgressivePolicy.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "VolumeImagePolicyBase.h"
-
-namespace OrthancStone
-{
-  class VolumeImageProgressivePolicy : public VolumeImagePolicyBase
-  {
-  private:
-    enum Quality
-    {
-      Quality_Low = 0,
-      Quality_Medium = 1,
-      Quality_Full = 2,
-      Quality_None = 3
-    };
-
-    class AxialSlicesScheduler;
-
-    std::auto_ptr<AxialSlicesScheduler>   scheduler_;
-    boost::mutex                          qualityMutex_;
-    std::vector<Quality>                  axialSlicesQuality_;
-    bool                                  isJpegAvailable_;
-
-    bool IsComplete();
-
-  protected:
-    virtual void InitializeInternal(ImageBuffer3D& buffer,
-                                    ISeriesLoader& loader);
-
-    virtual bool DownloadStepInternal(bool& complete,
-                                      ImageBuffer3D& buffer,
-                                      ISeriesLoader& loader);
-
-  public:
-    virtual bool IsFullQualityAxial(size_t slice);
-  };
-}
--- a/Framework/Volumes/VolumeImageSimplePolicy.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#include "VolumeImageSimplePolicy.h"
-
-#include "../../Resources/Orthanc/Core/Images/ImageProcessing.h"
-
-namespace OrthancStone
-{
-  void VolumeImageSimplePolicy::InitializeInternal(ImageBuffer3D& buffer,
-                                                   ISeriesLoader& loader)
-  {
-    boost::mutex::scoped_lock  lock(mutex_);
-
-    const size_t depth = loader.GetGeometry().GetSliceCount();
-    pendingSlices_.clear();
-
-    for (size_t i = 0; i < depth; i++)
-    {
-      pendingSlices_.insert(i);
-    }
-
-    doneSlices_.clear();
-    doneSlices_.resize(depth, false);
-  }
-
-
-  bool VolumeImageSimplePolicy::DownloadStepInternal(bool& complete,
-                                                     ImageBuffer3D& buffer,
-                                                     ISeriesLoader& loader)
-  {
-    size_t slice;
-
-    {
-      boost::mutex::scoped_lock  lock(mutex_);
-      
-      if (pendingSlices_.empty())
-      {
-        return true;
-      }
-      else
-      {
-        slice = *pendingSlices_.begin();
-        pendingSlices_.erase(slice);
-      }
-    }
-
-    std::auto_ptr<Orthanc::ImageAccessor> frame;
-
-    try
-    {
-      frame.reset(loader.DownloadFrame(slice));
-    }
-    catch (Orthanc::OrthancException&)
-    {
-      // The Orthanc server cannot decode this instance
-      return false;
-    }
-
-    if (frame.get() != NULL)
-    {
-      {
-        ImageBuffer3D::SliceWriter writer(buffer, VolumeProjection_Axial, slice);
-        Orthanc::ImageProcessing::Convert(writer.GetAccessor(), *frame);
-      }
-
-      {
-        boost::mutex::scoped_lock  lock(mutex_);
-
-        doneSlices_[slice] = true;
-
-        if (pendingSlices_.empty())
-        {
-          complete = true;
-          return true;
-        }
-      }
-    }
-      
-    return false;
-  }
-
-
-  bool VolumeImageSimplePolicy::IsFullQualityAxial(size_t slice)
-  {
-    boost::mutex::scoped_lock  lock(mutex_);
-    return doneSlices_[slice];
-  }
-}
--- a/Framework/Volumes/VolumeImageSimplePolicy.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "VolumeImagePolicyBase.h"
-
-namespace OrthancStone
-{
-  class VolumeImageSimplePolicy : public VolumeImagePolicyBase
-  {
-  private:
-    boost::mutex       mutex_;
-    std::set<size_t>   pendingSlices_;
-    std::vector<bool>  doneSlices_;
-
-  protected:
-    virtual void InitializeInternal(ImageBuffer3D& buffer,
-                                    ISeriesLoader& loader);
-
-    virtual bool DownloadStepInternal(bool& complete,
-                                      ImageBuffer3D& buffer,
-                                      ISeriesLoader& loader);
-
-  public:
-    virtual bool IsFullQualityAxial(size_t slice);
-  };
-}
--- a/Framework/Widgets/LayeredSceneWidget.cpp	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,595 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#define _USE_MATH_DEFINES  // To access M_PI in Visual Studio
-#include <cmath>
-
-#include "LayeredSceneWidget.h"
-
-#include "../../Resources/Orthanc/Core/OrthancException.h"
-
-#include <boost/thread/condition_variable.hpp>   // TODO Remove
-
-namespace OrthancStone
-{
-  class LayeredSceneWidget::Renderers : public boost::noncopyable
-  {
-  private:
-    boost::mutex                  mutex_;
-    std::vector<ILayerRenderer*>  renderers_;
-    std::vector<bool>             assigned_;
-      
-    void Assign(size_t index,
-                ILayerRenderer* renderer)
-    {
-      if (index >= renderers_.size())
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-      }
-        
-      if (renderers_[index] != NULL)
-      {
-        delete renderers_[index];
-      }
-
-      renderers_[index] = renderer;
-      assigned_[index] = true;
-    }
-
-  public:
-    Renderers(size_t size)
-    {
-      renderers_.resize(size);
-      assigned_.resize(size, false);
-    }
-
-    ~Renderers()
-    {
-      for (size_t i = 0; i < renderers_.size(); i++)
-      {
-        Assign(i, NULL);
-      }
-    }
-
-    static void Merge(Renderers& target,
-                      Renderers& source)
-    {
-      boost::mutex::scoped_lock lockSource(source.mutex_);
-      boost::mutex::scoped_lock lockTarget(target.mutex_);
-
-      size_t count = target.renderers_.size();
-      if (count != source.renderers_.size())
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-
-      for (size_t i = 0; i < count; i++)
-      {
-        if (source.assigned_[i])
-        {
-          target.Assign(i, source.renderers_[i]);  // Transfers ownership
-          source.renderers_[i] = NULL;
-          source.assigned_[i] = false;
-        }
-      }
-    }
-
-    void SetRenderer(size_t index,
-                     ILayerRenderer* renderer)  // Takes ownership
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      Assign(index, renderer);
-    }
-
-    bool RenderScene(CairoContext& context,
-                     const ViewportGeometry& view,
-                     const SliceGeometry& slice)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-
-      bool fullQuality = true;
-
-      for (size_t i = 0; i < renderers_.size(); i++)
-      {
-        if (renderers_[i] != NULL &&
-            !renderers_[i]->RenderLayer(context, view, slice))
-        {
-          return false;
-        }
-
-        if (renderers_[i] != NULL &&
-            !renderers_[i]->IsFullQuality())
-        {
-          fullQuality = false;
-        }
-      }
-
-      if (!fullQuality)
-      {
-        double x, y;
-        view.MapDisplayToScene(x, y, static_cast<double>(view.GetDisplayWidth()) / 2.0, 10);
-
-        cairo_t *cr = context.GetObject();
-        cairo_translate(cr, x, y);
-        cairo_arc(cr, 0, 0, 5.0 / view.GetZoom(), 0, 2 * M_PI);
-        cairo_set_line_width(cr, 2.0 / view.GetZoom());
-        cairo_set_source_rgb(cr, 1, 1, 1); 
-        cairo_stroke_preserve(cr);
-        cairo_set_source_rgb(cr, 1, 0, 0); 
-        cairo_fill(cr);
-      }
-
-      return true;
-    }
-
-    void SetLayerStyle(size_t index,
-                       const RenderStyle& style)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-        
-      if (renderers_[index] != NULL)
-      {
-        renderers_[index]->SetLayerStyle(style);
-      }
-    }
-  };
-
-
-
-  class LayeredSceneWidget::PendingLayers : public boost::noncopyable
-  {
-  private:
-    boost::mutex               mutex_;
-    boost::condition_variable  elementAvailable_;
-    size_t                     layerCount_;
-    std::list<size_t>          queue_;
-    std::vector<bool>          layersToUpdate_;
-    bool                       continue_;
-
-    void TagAllLayers()
-    {
-      queue_.clear();
-
-      for (unsigned int i = 0; i < layerCount_; i++)
-      {
-        queue_.push_back(i);
-        layersToUpdate_[i] = true;
-      }
-
-      if (layerCount_ != 0)
-      {
-        elementAvailable_.notify_one();
-      }
-    }
-      
-  public:
-    PendingLayers() : 
-      layerCount_(0), 
-      continue_(true)
-    {
-    }
-
-    void Stop()
-    {
-      continue_ = false;
-      elementAvailable_.notify_one();
-    }
-
-    void SetLayerCount(size_t count)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-
-      layerCount_ = count;
-      layersToUpdate_.resize(count);
-
-      TagAllLayers();
-    }
-
-    void InvalidateAllLayers()
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      TagAllLayers();
-    }
-
-    void InvalidateLayer(size_t layer)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-
-      if (layer < layerCount_)
-      {
-        if (layersToUpdate_[layer])
-        {
-          // The layer is already scheduled for update, ignore this
-          // invalidation
-        }
-        else
-        {
-          queue_.push_back(layer);
-          layersToUpdate_[layer] = true;
-          elementAvailable_.notify_one();
-        }
-      }
-    }
-
-    bool Dequeue(size_t& layer,
-                 bool& isLast)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-
-      // WARNING: Do NOT use "timed_wait" on condition variables, as
-      // sleeping is not properly supported by Boost for Google NaCl
-      while (queue_.empty() && 
-             continue_)
-      {
-        elementAvailable_.wait(lock);
-      }
-
-      if (!continue_)
-      {
-        return false;
-      }
-
-      layer = queue_.front();
-      layersToUpdate_[layer] = false;
-      queue_.pop_front();
-
-      isLast = queue_.empty();
-
-      return true;
-    }
-  };
-
-
-  class LayeredSceneWidget::Layer : public ISliceableVolume::IObserver
-  {
-  private:
-    boost::mutex                          mutex_;
-    std::auto_ptr<ILayerRendererFactory>  factory_;
-    PendingLayers&                        layers_;
-    size_t                                index_;
-    std::auto_ptr<RenderStyle>            style_;
-
-  public:
-    Layer(ILayerRendererFactory*  factory,
-          PendingLayers& layers,
-          size_t index) :
-      factory_(factory),
-      layers_(layers),
-      index_(index)
-    {
-      if (factory == NULL)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-      }
-    }
-
-    virtual void NotifyChange(const OrthancStone::ISliceableVolume&)
-    {
-      layers_.InvalidateLayer(index_);
-    }
-
-    void Start()
-    {
-      if (factory_->HasSourceVolume())
-      {
-        factory_->GetSourceVolume().Register(*this);
-      }
-    }
-
-    void Stop()
-    {
-      if (factory_->HasSourceVolume())
-      {
-        factory_->GetSourceVolume().Unregister(*this);
-      }
-    }
-
-    bool GetExtent(double& x1,
-                   double& y1,
-                   double& x2,
-                   double& y2,
-                   const SliceGeometry& displaySlice) 
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      assert(factory_.get() != NULL);
-      return factory_->GetExtent(x1, y1, x2, y2, displaySlice);
-    }
-
-    RenderStyle GetStyle() 
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-
-      if (style_.get() == NULL)
-      {
-        return RenderStyle();
-      }
-      else
-      {
-        return *style_;
-      }
-    }
-
-    void SetStyle(const RenderStyle& style)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      style_.reset(new RenderStyle(style));
-    }
-
-
-    ILayerRenderer* CreateRenderer(const SliceGeometry& displaySlice)
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      assert(factory_.get() != NULL);
-
-      std::auto_ptr<ILayerRenderer> renderer(factory_->CreateLayerRenderer(displaySlice));
-        
-      if (renderer.get() != NULL &&
-          style_.get() != NULL)
-      {
-        renderer->SetLayerStyle(*style_);
-      }
-
-      return renderer.release();
-    }
-  };
-
-
-
-  SliceGeometry LayeredSceneWidget::GetSlice()
-  {
-    boost::mutex::scoped_lock lock(sliceMutex_);
-    return slice_;
-  }
-
-
-  void LayeredSceneWidget::UpdateContent()
-  {
-    size_t layer = 0;
-    bool isLast = true;
-    if (!pendingLayers_->Dequeue(layer, isLast))
-    {
-      return;
-    }
-
-    SliceGeometry slice = GetSlice();
-
-    std::auto_ptr<ILayerRenderer> renderer;
-    renderer.reset(layers_[layer]->CreateRenderer(slice));
-
-    if (renderer.get() != NULL)
-    {
-      pendingRenderers_->SetRenderer(layer, renderer.release());
-    }
-    else
-    {
-      pendingRenderers_->SetRenderer(layer, NULL);
-    }
-
-    if (isLast)
-    {
-      Renderers::Merge(*renderers_, *pendingRenderers_);
-      NotifyChange();
-    }
-
-    // TODO Add sleep at this point
-  }
-    
-
-  bool LayeredSceneWidget::RenderScene(CairoContext& context,
-                                       const ViewportGeometry& view) 
-  {
-    return renderers_->RenderScene(context, view, slice_);
-  }
-
-
-  LayeredSceneWidget::LayeredSceneWidget() 
-  {
-    pendingLayers_.reset(new PendingLayers);
-    SetBackgroundCleared(true);
-  }
-
-
-  LayeredSceneWidget::~LayeredSceneWidget()
-  {
-    for (size_t i = 0; i < layers_.size(); i++)
-    {
-      assert(layers_[i] != NULL);
-      delete layers_[i];
-    }
-  }
-
-
-  void LayeredSceneWidget::GetSceneExtent(double& x1,
-                                          double& y1,
-                                          double& x2,
-                                          double& y2)
-  {
-    boost::mutex::scoped_lock lock(sliceMutex_);
-
-    bool first = true;
-
-    for (size_t i = 0; i < layers_.size(); i++)
-    {
-      double ax, ay, bx, by;
-
-      assert(layers_[i] != NULL);
-      if (layers_[i]->GetExtent(ax, ay, bx, by, slice_))
-      {
-        if (ax > bx)
-        {
-          std::swap(ax, bx);
-        }
-
-        if (ay > by)
-        {
-          std::swap(ay, by);
-        }
-
-        if (first)
-        {
-          x1 = ax;
-          y1 = ay;
-          x2 = bx;
-          y2 = by;
-          first = false;
-        }
-        else
-        {
-          x1 = std::min(x1, ax);
-          y1 = std::min(y1, ay);
-          x2 = std::max(x2, bx);
-          y2 = std::max(y2, by);
-        }
-      }
-    }
-
-    if (first)
-    {
-      x1 = -1;
-      y1 = -1;
-      x2 = 1;
-      y2 = 1;
-    }
-
-    // Ensure the extent is non-empty
-    if (x1 >= x2)
-    {
-      double tmp = x1;
-      x1 = tmp - 0.5;
-      x2 = tmp + 0.5;
-    }
-
-    if (y1 >= y2)
-    {
-      double tmp = y1;
-      y1 = tmp - 0.5;
-      y2 = tmp + 0.5;
-    }
-  }
-
-
-
-  ILayerRendererFactory& LayeredSceneWidget::AddLayer(size_t& layerIndex,
-                                                      ILayerRendererFactory* factory)
-  {
-    layerIndex = layers_.size();
-    layers_.push_back(new Layer(factory, *pendingLayers_, layers_.size()));
-
-    return *factory;
-  }
-
-
-  void LayeredSceneWidget::AddLayer(ILayerRendererFactory* factory)
-  {
-    size_t layerIndex;  // Ignored
-    AddLayer(layerIndex, factory);
-  }
-
-
-  RenderStyle LayeredSceneWidget::GetLayerStyle(size_t layer)
-  {
-    if (layer >= layers_.size())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    return layers_[layer]->GetStyle();
-  }
-
-
-  void LayeredSceneWidget::SetLayerStyle(size_t layer,
-                                         const RenderStyle& style)
-  {
-    if (layer >= layers_.size())
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    layers_[layer]->SetStyle(style);
-
-    if (renderers_.get() != NULL)
-    {
-      renderers_->SetLayerStyle(layer, style);
-    }
-
-    InvalidateLayer(layer);
-  }
-
-
-
-  void LayeredSceneWidget::SetSlice(const SliceGeometry& slice)
-  {
-    { 
-      boost::mutex::scoped_lock lock(sliceMutex_);
-      slice_ = slice;
-    }
-
-    InvalidateAllLayers();
-
-    observers_.Apply(*this, &ISliceObserver::NotifySliceChange, slice);
-  }
-
-
-  void LayeredSceneWidget::InvalidateLayer(unsigned int layer)
-  {
-    pendingLayers_->InvalidateLayer(layer);
-    //NotifyChange();  // TODO Understand why this makes the SDL engine not update the display subsequently
-  }
-
-
-  void LayeredSceneWidget::InvalidateAllLayers()
-  {
-    pendingLayers_->InvalidateAllLayers();
-    //NotifyChange();  // TODO Understand why this makes the SDL engine not update the display subsequently
-  }
-
-
-#if 0
-  void LayeredSceneWidget::Start()
-  {
-    for (size_t i = 0; i < layers_.size(); i++)
-    {
-      layers_[i]->Start();
-    }
-
-    renderers_.reset(new Renderers(layers_.size()));
-    pendingRenderers_.reset(new Renderers(layers_.size()));
-
-    pendingLayers_->SetLayerCount(layers_.size());
-
-    WorldSceneWidget::Start();
-  }
-
-
-  void LayeredSceneWidget::Stop()
-  {
-    pendingLayers_->Stop();
-
-    renderers_.reset(NULL);
-    pendingRenderers_.reset(NULL);
-
-    for (size_t i = 0; i < layers_.size(); i++)
-    {
-      layers_[i]->Stop();
-    }
-  }
-#endif
-}
--- a/Framework/Widgets/LayeredSceneWidget.h	Wed Jun 14 14:21:24 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017 Osimis, Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "WorldSceneWidget.h"
-
-#include "../Layers/ILayerRendererFactory.h"
-#include "../Toolbox/ObserversRegistry.h"
-
-#include <boost/thread/mutex.hpp>  // TODO remove
-
-namespace OrthancStone
-{
-  class LayeredSceneWidget : public WorldSceneWidget
-  {
-  public:
-    class ISliceObserver : public boost::noncopyable
-    {
-    public:
-      virtual ~ISliceObserver()
-      {
-      }
-
-      virtual void NotifySliceChange(const LayeredSceneWidget& source,
-                                     const SliceGeometry& slice) = 0;
-    };
-
-  private:
-    class Renderers;
-    class PendingLayers;
-    class Layer;
-
-    typedef ObserversRegistry<LayeredSceneWidget, ISliceObserver>  Observers;
-
-    std::vector<Layer*>           layers_;
-    std::auto_ptr<Renderers>      renderers_;
-    std::auto_ptr<PendingLayers>  pendingLayers_;
-    std::auto_ptr<Renderers>      pendingRenderers_;
-    boost::mutex                  sliceMutex_;
-    SliceGeometry                 slice_;
-    Observers                     observers_;
-
-  protected:
-    virtual void GetSceneExtent(double& x1,
-                                double& y1,
-                                double& x2,
-                                double& y2);
-
-    virtual bool RenderScene(CairoContext& context,
-                             const ViewportGeometry& view);
-
-  public:
-    LayeredSceneWidget();
-
-    virtual ~LayeredSceneWidget();
-
-    SliceGeometry GetSlice();
-
-    ILayerRendererFactory& AddLayer(size_t& layerIndex,
-                                    ILayerRendererFactory* factory);   // Takes ownership
-
-    // Simpler version for basic use cases
-    void AddLayer(ILayerRendererFactory* factory);   // Takes ownership
-
-    size_t GetLayerCount() const
-    {
-      return layers_.size();
-    }
-
-    RenderStyle GetLayerStyle(size_t layer);
-    
-    void SetLayerStyle(size_t layer,
-                       const RenderStyle& style);
-
-    void SetSlice(const SliceGeometry& slice);
-
-    void InvalidateLayer(unsigned int layer);
-
-    void InvalidateAllLayers();
-
-    using WorldSceneWidget::Register;
-    using WorldSceneWidget::Unregister;
-
-    void Register(ISliceObserver& observer)
-    {
-      observers_.Register(observer);
-    }
-
-    void Unregister(ISliceObserver& observer)
-    {
-      observers_.Unregister(observer);
-    }
-
-    virtual bool HasUpdateContent() const
-    {
-      return true;
-    }
-
-    virtual void UpdateContent();
-  };
-}
--- a/Resources/CMake/OrthancStone.cmake	Wed Jun 14 14:21:24 2017 +0200
+++ b/Resources/CMake/OrthancStone.cmake	Wed Jun 14 15:07:07 2017 +0200
@@ -193,11 +193,6 @@
   #${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/Volumes/VolumeImage.cpp
-  #${ORTHANC_STONE_DIR}/Framework/Volumes/VolumeImagePolicyBase.cpp
-  #${ORTHANC_STONE_DIR}/Framework/Volumes/VolumeImageProgressivePolicy.cpp
-  #${ORTHANC_STONE_DIR}/Framework/Volumes/VolumeImageSimplePolicy.cpp
-  #${ORTHANC_STONE_DIR}/Framework/Widgets/LayeredSceneWidget.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/CircleMeasureTracker.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/ColorFrameRenderer.cpp
   ${ORTHANC_STONE_DIR}/Framework/Layers/FrameRenderer.cpp