changeset 1029:0f100d0b9caf

merge
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 04 Oct 2019 21:58:30 +0200
parents 6d5382fa45e1 (current diff) 7912de3a15e0 (diff)
children 7b89e88bb66e
files
diffstat 52 files changed, 888 insertions(+), 259 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Oct 04 21:58:13 2019 +0200
+++ b/.hgtags	Fri Oct 04 21:58:30 2019 +0200
@@ -30,3 +30,4 @@
 4fda090b016b3fc3405d442abfde7d6e1d9b17fe toa2019092002
 efe1c44628a1fc6386a936ad0e42f79a4ba61e6b toa2019092003
 53cc787bd7bce69639a6003ee20c8a2b304030e4 toa2019092301
+ac88989817e3b4249ebab6a824466bbb62f70452 toa2019093001
--- a/Applications/Generic/GuiAdapter.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Applications/Generic/GuiAdapter.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -78,6 +78,9 @@
     case EMSCRIPTEN_EVENT_MOUSEDOWN:
       dest.type = GUIADAPTER_EVENT_MOUSEDOWN;
       break;
+    case EMSCRIPTEN_EVENT_DBLCLICK:
+      dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK;
+      break;
     case EMSCRIPTEN_EVENT_MOUSEMOVE:
       dest.type = GUIADAPTER_EVENT_MOUSEMOVE;
       break;
@@ -287,6 +290,19 @@
       func);
   }
 
+  
+  void GuiAdapter::SetMouseDblClickCallback(
+      std::string canvasId, void* userData, bool capture, OnMouseEventFunc func)
+  {
+    SetCallback<OnMouseEventFunc, GuiAdapterMouseEvent, EmscriptenMouseEvent>(
+      &emscripten_set_dblclick_callback_on_thread,
+      canvasId,
+      userData,
+      capture,
+      func);
+  }
+
+
   void GuiAdapter::SetMouseDownCallback(
     std::string canvasId, void* userData, bool capture, OnMouseEventFunc func)
   {
@@ -401,7 +417,14 @@
     switch (source.type)
     {
     case SDL_MOUSEBUTTONDOWN:
-      dest.type = GUIADAPTER_EVENT_MOUSEDOWN;
+      if (source.button.clicks == 1) {
+        dest.type = GUIADAPTER_EVENT_MOUSEDOWN;
+      } else if (source.button.clicks == 2) {
+        dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK;
+      } else {
+        dest.type = GUIADAPTER_EVENT_MOUSEDBLCLICK;
+        LOG(WARNING) << "Multiple-click ignored.";
+      }
       break;
     case SDL_MOUSEMOTION:
       dest.type = GUIADAPTER_EVENT_MOUSEMOVE;
@@ -513,6 +536,13 @@
   }
 
   // SDL ONLY
+  void GuiAdapter::SetMouseDblClickCallback(
+    std::string canvasId, void* userData, bool capture, OnMouseEventFunc func)
+  {
+    mouseDblCickHandlers_.push_back(EventHandlerData<OnMouseEventFunc>(canvasId, func, userData));
+  }
+
+  // SDL ONLY
   void GuiAdapter::SetMouseMoveCallback(
     std::string canvasId, void* userData, bool capture, OnMouseEventFunc  func)
   {
@@ -674,6 +704,13 @@
             (*(mouseDownHandlers_[i].func))(windowTitle, &event, mouseDownHandlers_[i].userData);
         }
         break;
+      case GUIADAPTER_EVENT_MOUSEDBLCLICK:
+        for (size_t i = 0; i < mouseDblCickHandlers_.size(); i++)
+        {
+          if (mouseDblCickHandlers_[i].canvasName == windowTitle)
+            (*(mouseDblCickHandlers_[i].func))(windowTitle, &event, mouseDblCickHandlers_[i].userData);
+        }
+        break;
       case GUIADAPTER_EVENT_MOUSEMOVE:
         for (size_t i = 0; i < mouseMoveHandlers_.size(); i++)
         {
--- a/Applications/Generic/GuiAdapter.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Applications/Generic/GuiAdapter.h	Fri Oct 04 21:58:30 2019 +0200
@@ -77,12 +77,13 @@
 
   enum GuiAdapterHidEventType
   {
-    GUIADAPTER_EVENT_MOUSEDOWN = 1973,
-    GUIADAPTER_EVENT_MOUSEMOVE = 1974,
-    GUIADAPTER_EVENT_MOUSEUP   = 1975,
-    GUIADAPTER_EVENT_WHEEL     = 1976,
-    GUIADAPTER_EVENT_KEYDOWN   = 1977,
-    GUIADAPTER_EVENT_KEYUP     = 1978,
+    GUIADAPTER_EVENT_MOUSEDOWN      = 1973,
+    GUIADAPTER_EVENT_MOUSEMOVE      = 1974,
+    GUIADAPTER_EVENT_MOUSEDBLCLICK  = 1975,
+    GUIADAPTER_EVENT_MOUSEUP        = 1976,
+    GUIADAPTER_EVENT_WHEEL          = 1977,
+    GUIADAPTER_EVENT_KEYDOWN        = 1978,
+    GUIADAPTER_EVENT_KEYUP          = 1979,
   };
 
   const unsigned int GUIADAPTER_DELTA_PIXEL = 2973;
@@ -253,12 +254,13 @@
 
     */
 
-    void SetMouseDownCallback(std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
-    void SetMouseMoveCallback(std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
-    void SetMouseUpCallback  (std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
-    void SetWheelCallback    (std::string canvasId, void* userData, bool capture, OnMouseWheelFunc   func);
-    void SetKeyDownCallback  (std::string canvasId, void* userData, bool capture, OnKeyDownFunc      func);
-    void SetKeyUpCallback    (std::string canvasId, void* userData, bool capture, OnKeyUpFunc        func);
+    void SetMouseDownCallback     (std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
+    void SetMouseDblClickCallback (std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
+    void SetMouseMoveCallback     (std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
+    void SetMouseUpCallback       (std::string canvasId, void* userData, bool capture, OnMouseEventFunc   func);
+    void SetWheelCallback         (std::string canvasId, void* userData, bool capture, OnMouseWheelFunc   func);
+    void SetKeyDownCallback       (std::string canvasId, void* userData, bool capture, OnKeyDownFunc      func);
+    void SetKeyUpCallback         (std::string canvasId, void* userData, bool capture, OnKeyUpFunc        func);
     
     // if you pass "#window", under SDL, then any Window resize will trigger the callback
     void SetResizeCallback (std::string canvasId, void* userData, bool capture, OnWindowResizeFunc func);
@@ -330,6 +332,7 @@
     };
     std::vector<EventHandlerData<OnWindowResizeFunc> > resizeHandlers_;
     std::vector<EventHandlerData<OnMouseEventFunc  > > mouseDownHandlers_;
+    std::vector<EventHandlerData<OnMouseEventFunc  > > mouseDblCickHandlers_;
     std::vector<EventHandlerData<OnMouseEventFunc  > > mouseMoveHandlers_;
     std::vector<EventHandlerData<OnMouseEventFunc  > > mouseUpHandlers_;
     std::vector<EventHandlerData<OnMouseWheelFunc  > > mouseWheelHandlers_;
--- a/Framework/Loaders/DicomStructureSetLoader.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/DicomStructureSetLoader.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -24,6 +24,8 @@
 #include "../Scene2D/PolylineSceneLayer.h"
 #include "../Toolbox/GeometryToolbox.h"
 
+#include <algorithm>
+
 #if 0
 bool logbgo233 = false;
 bool logbgo115 = false;
@@ -153,8 +155,7 @@
     State(that)
     {
     }
-
-
+    
     virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
     {
 #if 0
@@ -166,6 +167,33 @@
       {
         OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer());
         loader.content_.reset(new DicomStructureSet(dicom));
+        size_t structureCount = loader.content_->GetStructuresCount();
+        loader.structureVisibility_.resize(structureCount);
+        for (size_t i = 0; i < structureCount; ++i)
+        {
+          // if nothing is specified in the ctor, this means we want everything visible
+          if (loader.initiallyVisibleStructures_.size() == 0)
+          {
+            loader.structureVisibility_.at(i) = true;
+          }
+          else
+          {
+            // otherwise, we only enable visibility for those structures whose 
+            // names are mentioned in the initiallyVisibleStructures_ array
+            const std::string& structureName = loader.content_->GetStructureName(i);
+
+            std::vector<std::string>::iterator foundIt =
+              std::find(
+                loader.initiallyVisibleStructures_.begin(),
+                loader.initiallyVisibleStructures_.end(),
+                structureName);
+            std::vector<std::string>::iterator endIt = loader.initiallyVisibleStructures_.end();
+            if (foundIt != endIt)
+              loader.structureVisibility_.at(i) = true;
+            else
+              loader.structureVisibility_.at(i) = false;
+          }
+        }
       }
 
       // Some (admittedly invalid) Dicom files have empty values in the 
@@ -204,14 +232,30 @@
     const DicomStructureSet&  content_;
     uint64_t                  revision_;
     bool                      isValid_;
+    std::vector<bool>         visibility_;
       
   public:
+    /**
+    The visibility vector must either:
+    - be empty
+    or
+    - contain the same number of items as the number of structures in the 
+      structure set.
+    In the first case (empty vector), all the structures are displayed.
+    In the second case, the visibility of each structure is defined by the 
+    content of the vector at the corresponding index.
+    */
     Slice(const DicomStructureSet& content,
           uint64_t revision,
-          const CoordinateSystem3D& cuttingPlane) :
-      content_(content),
-      revision_(revision)
+          const CoordinateSystem3D& cuttingPlane,
+          std::vector<bool> visibility = std::vector<bool>()) 
+      : content_(content)
+      , revision_(revision)
+      , visibility_(visibility)
     {
+      ORTHANC_ASSERT((visibility_.size() == content_.GetStructuresCount())
+        || (visibility_.size() == 0u));
+
       bool opposite;
 
       const Vector normal = content.GetNormal();
@@ -241,43 +285,46 @@
 
       for (size_t i = 0; i < content_.GetStructuresCount(); i++)
       {
-        const Color& color = content_.GetStructureColor(i);
+        if ((visibility_.size() == 0) || visibility_.at(i))
+        {
+          const Color& color = content_.GetStructureColor(i);
 
 #ifdef USE_BOOST_UNION_FOR_POLYGONS 
-        std::vector< std::vector<Point2D> > polygons;
-          
-        if (content_.ProjectStructure(polygons, i, cuttingPlane))
-        {
-          for (size_t j = 0; j < polygons.size(); j++)
+          std::vector< std::vector<Point2D> > polygons;
+
+          if (content_.ProjectStructure(polygons, i, cuttingPlane))
           {
-            PolylineSceneLayer::Chain chain;
-            chain.resize(polygons[j].size());
-            
-            for (size_t k = 0; k < polygons[j].size(); k++)
+            for (size_t j = 0; j < polygons.size(); j++)
             {
-              chain[k] = ScenePoint2D(polygons[j][k].x, polygons[j][k].y);
-            }
+              PolylineSceneLayer::Chain chain;
+              chain.resize(polygons[j].size());
 
-            layer->AddChain(chain, true /* closed */, color);
-          }
+              for (size_t k = 0; k < polygons[j].size(); k++)
+              {
+                chain[k] = ScenePoint2D(polygons[j][k].x, polygons[j][k].y);
+    }
+
+              layer->AddChain(chain, true /* closed */, color);
+  }
         }
 #else
-        std::vector< std::pair<Point2D, Point2D> > segments;
+          std::vector< std::pair<Point2D, Point2D> > segments;
 
-        if (content_.ProjectStructure(segments, i, cuttingPlane))
-        {
-          for (size_t j = 0; j < segments.size(); j++)
+          if (content_.ProjectStructure(segments, i, cuttingPlane))
           {
-            PolylineSceneLayer::Chain chain;
-            chain.resize(2);
+            for (size_t j = 0; j < segments.size(); j++)
+            {
+              PolylineSceneLayer::Chain chain;
+              chain.resize(2);
 
-            chain[0] = ScenePoint2D(segments[j].first.x, segments[j].first.y);
-            chain[1] = ScenePoint2D(segments[j].second.x, segments[j].second.y);
+              chain[0] = ScenePoint2D(segments[j].first.x, segments[j].first.y);
+              chain[1] = ScenePoint2D(segments[j].second.x, segments[j].second.y);
 
-            layer->AddChain(chain, false /* NOT closed */, color);
+              layer->AddChain(chain, false /* NOT closed */, color);
+            }
           }
+#endif        
         }
-#endif
       }
 
       return layer.release();
@@ -297,17 +344,26 @@
   }
     
     
+  void DicomStructureSetLoader::SetStructureDisplayState(size_t structureIndex, bool display)
+  {
+    structureVisibility_.at(structureIndex) = display;
+    revision_++;
+  }
+
   DicomStructureSetLoader::~DicomStructureSetLoader()
   {
     LOG(TRACE) << "DicomStructureSetLoader::~DicomStructureSetLoader()";
   }
 
-  void DicomStructureSetLoader::LoadInstance(const std::string& instanceId)
+  void DicomStructureSetLoader::LoadInstance(
+    const std::string& instanceId, 
+    const std::vector<std::string>& initiallyVisibleStructures)
   {
     Start();
       
     instanceId_ = instanceId;
-      
+    initiallyVisibleStructures_ = initiallyVisibleStructures;
+
     {
       std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
       command->SetHttpHeader("Accept-Encoding", "gzip");
@@ -330,7 +386,7 @@
     }
     else
     {
-      return new Slice(*content_, revision_, cuttingPlane);
+      return new Slice(*content_, revision_, cuttingPlane, structureVisibility_);
     }
   }
 
--- a/Framework/Loaders/DicomStructureSetLoader.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/DicomStructureSetLoader.h	Fri Oct 04 21:58:30 2019 +0200
@@ -25,6 +25,8 @@
 #include "../Volumes/IVolumeSlicer.h"
 #include "LoaderStateMachine.h"
 
+#include <vector>
+
 namespace OrthancStone
 {
   class DicomStructureSetLoader :
@@ -48,16 +50,46 @@
 
     // will be set to true once the loading is finished
     bool                              structuresReady_;
-    
+
+    /**
+    At load time, these strings is used to initialize the 
+    structureVisibility_ vector.
+
+    As a special case, if initiallyVisibleStructures_ is empty, ALL structures
+    will be made visible.
+    */
+    std::vector<std::string> initiallyVisibleStructures_;
+
+    /**
+    Contains the "Should this structure be displayed?" flag for all structures.
+    Only filled when structures are loaded.
+
+    Changing this value directly affects the rendering
+    */
+    std::vector<bool>                  structureVisibility_;
+
   public:
     ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, StructuresReady, DicomStructureSetLoader);
 
     DicomStructureSetLoader(IOracle& oracle,
                             IObservable& oracleObservable);    
     
+    DicomStructureSet* GetContent()
+    {
+      return content_.get();
+    }
+
+    void SetStructureDisplayState(size_t structureIndex, bool display);
+    
+    bool GetStructureDisplayState(size_t structureIndex) const
+    {
+      return structureVisibility_.at(structureIndex);
+    }
+
     ~DicomStructureSetLoader();
     
-    void LoadInstance(const std::string& instanceId);
+    void LoadInstance(const std::string& instanceId, 
+                      const std::vector<std::string>& initiallyVisibleStructures = std::vector<std::string>());
 
     virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane) ORTHANC_OVERRIDE;
 
--- a/Framework/Loaders/DicomStructureSetLoader2.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/DicomStructureSetLoader2.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -18,6 +18,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructureSetLoader2.h"
 
 #include "../Messages/IObservable.h"
@@ -117,3 +119,7 @@
   */
 
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/Framework/Loaders/DicomStructureSetLoader2.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/DicomStructureSetLoader2.h	Fri Oct 04 21:58:30 2019 +0200
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "../Toolbox/DicomStructureSet2.h"
 #include "../Messages/IMessage.h"
 #include "../Messages/IObserver.h"
@@ -78,3 +80,8 @@
     bool                structuresReady_;
   };
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
--- a/Framework/Loaders/LoaderCache.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/LoaderCache.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -23,7 +23,12 @@
 #include "OrthancSeriesVolumeProgressiveLoader.h"
 #include "OrthancMultiframeVolumeLoader.h"
 #include "DicomStructureSetLoader.h"
+
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 #include "DicomStructureSetLoader2.h"
+#endif 
+ //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 
 #if ORTHANC_ENABLE_WASM == 1
 # include <unistd.h>
@@ -33,10 +38,19 @@
 #endif
 
 #include "../Messages/LockingEmitter.h"
+
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 #include "../Toolbox/DicomStructureSet2.h"
+#endif 
+//BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "../Volumes/DicomVolumeImage.h"
 #include "../Volumes/DicomVolumeImageMPRSlicer.h"
+
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 #include "../Volumes/DicomStructureSetSlicer2.h"
+#endif 
+//BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 
 #include <Core/OrthancException.h>
 #include <Core/Toolbox.h>
@@ -187,6 +201,8 @@
     }
   }
   
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
   boost::shared_ptr<DicomStructureSetSlicer2> LoaderCache::GetDicomStructureSetSlicer2(std::string instanceUuid)
   {
     // if the loader is not available, let's trigger its creation
@@ -198,17 +214,52 @@
 
     return dicomStructureSetSlicers2_[instanceUuid];
   }
+#endif
+//BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 
-  boost::shared_ptr<DicomStructureSetLoader> LoaderCache::GetDicomStructureSetLoader(std::string instanceUuid)
+
+  /**
+  This method allows to convert a list of string into a string by 
+  sorting the strings then joining them
+  */
+  static std::string SortAndJoin(const std::vector<std::string>& stringList)
+  {
+    if (stringList.size() == 0)
+    {
+      return "";
+    } 
+    else
+    {
+      std::vector<std::string> sortedStringList = stringList;
+      std::sort(sortedStringList.begin(), sortedStringList.end());
+      std::stringstream s;
+      s << sortedStringList[0];
+      for (size_t i = 1; i < sortedStringList.size(); ++i)
+      {
+        s << "-" << sortedStringList[i];
+      }
+      return s.str();
+    }
+  }
+  
+  boost::shared_ptr<DicomStructureSetLoader> 
+    LoaderCache::GetDicomStructureSetLoader(
+      std::string inInstanceUuid, 
+      const std::vector<std::string>& initiallyVisibleStructures)
   {
     try
     {
       // normalize keys a little
-      instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid);
-      Orthanc::Toolbox::ToLowerCase(instanceUuid);
+      inInstanceUuid = Orthanc::Toolbox::StripSpaces(inInstanceUuid);
+      Orthanc::Toolbox::ToLowerCase(inInstanceUuid);
+
+      std::string initiallyVisibleStructuresKey = 
+        SortAndJoin(initiallyVisibleStructures);
+
+      std::string entryKey = inInstanceUuid + "_" + initiallyVisibleStructuresKey;
 
       // find in cache
-      if (dicomStructureSetLoaders_.find(instanceUuid) == dicomStructureSetLoaders_.end())
+      if (dicomStructureSetLoaders_.find(entryKey) == dicomStructureSetLoaders_.end())
       {
         boost::shared_ptr<DicomStructureSetLoader> loader;
 
@@ -219,11 +270,11 @@
           LockingEmitter::WriterLock lock(lockingEmitter_);
           loader.reset(new DicomStructureSetLoader(oracle_, lock.GetOracleObservable()));
 #endif
-          loader->LoadInstance(instanceUuid);
+          loader->LoadInstance(inInstanceUuid, initiallyVisibleStructures);
         }
-        dicomStructureSetLoaders_[instanceUuid] = loader;
+        dicomStructureSetLoaders_[entryKey] = loader;
       }
-      return dicomStructureSetLoaders_[instanceUuid];
+      return dicomStructureSetLoaders_[entryKey];
     }
     catch (const Orthanc::OrthancException& e)
     {
@@ -249,6 +300,7 @@
     }
   }
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 
   boost::shared_ptr<DicomStructureSetLoader2> LoaderCache::GetDicomStructureSetLoader2(std::string instanceUuid)
   {
@@ -304,6 +356,10 @@
     }
   }
 
+#endif
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
   void LoaderCache::ClearCache()
   {
 #if ORTHANC_ENABLE_WASM != 1
@@ -319,10 +375,13 @@
     dicomVolumeImageMPRSlicers_.clear();
     dicomStructureSetLoaders_.clear();
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
     // order is important!
     dicomStructureSetLoaders2_.clear();
     dicomStructureSetSlicers2_.clear();
     dicomStructureSets2_.clear();
+#endif
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
   }
 
   template<typename T> void DebugDisplayObjRefCountsInMap(
@@ -344,7 +403,10 @@
     DebugDisplayObjRefCountsInMap("multiframeVolumeLoaders_", multiframeVolumeLoaders_);
     DebugDisplayObjRefCountsInMap("dicomVolumeImageMPRSlicers_", dicomVolumeImageMPRSlicers_);
     DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders_", dicomStructureSetLoaders_);
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
     DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders2_", dicomStructureSetLoaders2_);
     DebugDisplayObjRefCountsInMap("dicomStructureSetSlicers2_", dicomStructureSetSlicers2_);
+#endif
+//BGO_ENABLE_DICOMSTRUCTURESETLOADER2
   }
 }
--- a/Framework/Loaders/LoaderCache.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Loaders/LoaderCache.h	Fri Oct 04 21:58:30 2019 +0200
@@ -24,15 +24,19 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 namespace OrthancStone
 {
   class OrthancSeriesVolumeProgressiveLoader;
   class DicomVolumeImageMPRSlicer;
   class DicomStructureSetLoader;
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
   class DicomStructureSetLoader2;
   class DicomStructureSetSlicer2;
   class DicomStructureSet2;
+#endif 
+  //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
   class OrthancMultiframeVolumeLoader;
 
 #if ORTHANC_ENABLE_WASM == 1
@@ -61,13 +65,18 @@
       GetMultiframeVolumeLoader(std::string instanceUuid);
 
     boost::shared_ptr<DicomStructureSetLoader>
-      GetDicomStructureSetLoader            (std::string instanceUuid);
+      GetDicomStructureSetLoader(
+        std::string instanceUuid,
+        const std::vector<std::string>& initiallyVisibleStructures);
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
     boost::shared_ptr<DicomStructureSetLoader2>
       GetDicomStructureSetLoader2(std::string instanceUuid);
 
     boost::shared_ptr<DicomStructureSetSlicer2>
       GetDicomStructureSetSlicer2(std::string instanceUuid);
+#endif 
+    //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 
     void ClearCache();
 
@@ -89,12 +98,15 @@
       dicomVolumeImageMPRSlicers_;
     std::map<std::string, boost::shared_ptr<DicomStructureSetLoader> >
       dicomStructureSetLoaders_;
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
     std::map<std::string, boost::shared_ptr<DicomStructureSetLoader2> >
       dicomStructureSetLoaders2_;
     std::map<std::string, boost::shared_ptr<DicomStructureSet2> >
       dicomStructureSets2_;
     std::map<std::string, boost::shared_ptr<DicomStructureSetSlicer2> >
       dicomStructureSetSlicers2_;
+#endif 
+    //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
   };
 }
 
--- a/Framework/Radiography/RadiographySceneReader.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Radiography/RadiographySceneReader.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -140,7 +140,6 @@
     }
   }
 
-
   void RadiographySceneReader::Read(const Json::Value& input)
   {
     unsigned int version = input["version"].asUInt();
@@ -228,6 +227,19 @@
     }
   }
 
+  void RadiographySceneBuilder::ReadDicomLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input)
+  {
+    for(size_t layerIndex = 0; layerIndex < input["layers"].size(); layerIndex++)
+    {
+      const Json::Value& jsonLayer = input["layers"][(int)layerIndex];
+      if (jsonLayer["type"].asString() == "dicom")
+      {
+        ReadLayerGeometry(geometry, jsonLayer);
+        return;
+      }
+    }
+  }
+
   void RadiographySceneBuilder::ReadLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& jsonLayer)
   {
     {// crop
--- a/Framework/Radiography/RadiographySceneReader.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Radiography/RadiographySceneReader.h	Fri Oct 04 21:58:30 2019 +0200
@@ -64,9 +64,12 @@
       fontRegistry_ = &fontRegistry;
     }
 
+    static void ReadLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input);
+    static void ReadDicomLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input);
+
   protected:
-    void ReadLayerGeometry(RadiographyLayer::Geometry& geometry, const Json::Value& input);
     virtual RadiographyDicomLayer* LoadDicom(const std::string& instanceId, unsigned int frame, RadiographyLayer::Geometry* geometry);
+
   };
 
 
--- a/Framework/Scene2DViewport/AngleMeasureTool.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -115,6 +115,13 @@
     RefreshScene();
   }
 
+  std::string AngleMeasureTool::GetDescription()
+  {
+    std::stringstream ss;
+    ss << "AngleMeasureTool. Center = " << center_ << " Side1End = " << side1End_ << " Side2End = " << side2End_;
+    return ss.str();
+  }
+
   void AngleMeasureTool::Highlight(ScenePoint2D p)
   {
     AngleHighlightArea angleHighlightArea = AngleHitTest(p);
--- a/Framework/Scene2DViewport/AngleMeasureTool.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/AngleMeasureTool.h	Fri Oct 04 21:58:30 2019 +0200
@@ -54,6 +54,7 @@
     virtual boost::shared_ptr<IFlexiblePointerTracker> CreateEditionTracker(const PointerEvent& e) ORTHANC_OVERRIDE;
     virtual boost::shared_ptr<MeasureToolMemento> GetMemento() const ORTHANC_OVERRIDE;
     virtual void SetMemento(boost::shared_ptr<MeasureToolMemento>) ORTHANC_OVERRIDE;
+    virtual std::string GetDescription() ORTHANC_OVERRIDE;
 
     enum AngleHighlightArea
     {
--- a/Framework/Scene2DViewport/CreateAngleMeasureCommand.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureCommand.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,53 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "CreateAngleMeasureCommand.h"
+
+#include <boost/make_shared.hpp>
+#include <boost/ref.hpp>
+
+namespace OrthancStone
+{
+  CreateAngleMeasureCommand::CreateAngleMeasureCommand(
+    MessageBroker& broker,
+    boost::weak_ptr<ViewportController> controllerW,
+    ScenePoint2D           point)
+    : CreateMeasureCommand(controllerW)
+    , measureTool_(
+      boost::make_shared<AngleMeasureTool>(boost::ref(broker), controllerW))
+  {
+    GetController()->AddMeasureTool(measureTool_);
+    measureTool_->SetSide1End(point);
+    measureTool_->SetCenter(point);
+    measureTool_->SetSide2End(point);
+  }
+
+  /** This method sets center*/
+  void CreateAngleMeasureCommand::SetCenter(ScenePoint2D scenePos)
+  {
+    measureTool_->SetCenter(scenePos);
+  }
+
+  /** This method sets end of side 2*/
+  void CreateAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos)
+  {
+    measureTool_->SetSide2End(scenePos);
+  }
+}
--- a/Framework/Scene2DViewport/CreateAngleMeasureCommand.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureCommand.h	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,48 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "MeasureCommands.h"
+
+namespace OrthancStone
+{
+  class CreateAngleMeasureCommand : public CreateMeasureCommand
+  {
+  public:
+    /** Ctor sets end of side 1*/
+    CreateAngleMeasureCommand(
+      MessageBroker& broker,
+      boost::weak_ptr<ViewportController> controllerW,
+      ScenePoint2D           point);
+
+    /** This method sets center*/
+    void SetCenter(ScenePoint2D scenePos);
+
+    /** This method sets end of side 2*/
+    void SetSide2End(ScenePoint2D scenePos);
+
+  private:
+    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
+    {
+      return measureTool_;
+    }
+    boost::shared_ptr<AngleMeasureTool> measureTool_;
+  };
+}
--- a/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -19,6 +19,8 @@
  **/
 
 #include "CreateAngleMeasureTracker.h"
+#include "CreateAngleMeasureCommand.h"
+
 #include <Core/OrthancException.h>
 
 namespace OrthancStone
--- a/Framework/Scene2DViewport/CreateLineMeasureCommand.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureCommand.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,44 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "CreateLineMeasureCommand.h"
+
+#include <boost/make_shared.hpp>
+#include <boost/ref.hpp>
+
+namespace OrthancStone
+{
+  CreateLineMeasureCommand::CreateLineMeasureCommand(
+    MessageBroker& broker,
+    boost::weak_ptr<ViewportController> controllerW,
+    ScenePoint2D           point)
+    : CreateMeasureCommand(controllerW)
+    , measureTool_(
+      boost::make_shared<LineMeasureTool>(boost::ref(broker), controllerW))
+  {
+    GetController()->AddMeasureTool(measureTool_);
+    measureTool_->Set(point, point);
+  }
+
+  void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos)
+  {
+    measureTool_->SetEnd(scenePos);
+  }
+}
--- a/Framework/Scene2DViewport/CreateLineMeasureCommand.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureCommand.h	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,46 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "MeasureCommands.h"
+
+namespace OrthancStone
+{
+  class CreateLineMeasureCommand : public CreateMeasureCommand
+  {
+  public:
+    CreateLineMeasureCommand(
+      MessageBroker& broker,
+      boost::weak_ptr<ViewportController> controllerW,
+      ScenePoint2D           point);
+
+    // the starting position is set in the ctor
+    void SetEnd(ScenePoint2D scenePos);
+
+  private:
+    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
+    {
+      return measureTool_;
+    }
+    boost::shared_ptr<LineMeasureTool> measureTool_;
+  };
+}
+
+
--- a/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -19,6 +19,8 @@
  **/
 
 #include "CreateLineMeasureTracker.h"
+#include "CreateLineMeasureCommand.h"
+
 #include <Core/OrthancException.h>
 
 namespace OrthancStone
--- a/Framework/Scene2DViewport/CreateLineMeasureTracker.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h	Fri Oct 04 21:58:30 2019 +0200
@@ -22,6 +22,9 @@
 
 #include "MeasureTrackers.h"
 
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
 namespace OrthancStone
 {
   class CreateLineMeasureTracker : public CreateMeasureTracker
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,53 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "EditAngleMeasureCommand.h"
+
+namespace OrthancStone
+{
+  EditAngleMeasureCommand::EditAngleMeasureCommand(
+    boost::shared_ptr<AngleMeasureTool>  measureTool,
+    MessageBroker& broker,
+    boost::weak_ptr<ViewportController> controllerW)
+    : EditMeasureCommand(measureTool, controllerW)
+    , measureTool_(measureTool)
+  {
+  }
+
+  void EditAngleMeasureCommand::SetCenter(ScenePoint2D scenePos)
+  {
+    measureTool_->SetCenter(scenePos);
+    mementoModified_ = measureTool_->GetMemento();
+  }
+
+
+  void EditAngleMeasureCommand::SetSide1End(ScenePoint2D scenePos)
+  {
+    measureTool_->SetSide1End(scenePos);
+    mementoModified_ = measureTool_->GetMemento();
+  }
+
+
+  void EditAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos)
+  {
+    measureTool_->SetSide2End(scenePos);
+    mementoModified_ = measureTool_->GetMemento();
+  }
+}
--- a/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureCommand.h	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,51 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "MeasureCommands.h"
+
+namespace OrthancStone
+{
+  class EditAngleMeasureCommand : public EditMeasureCommand
+  {
+  public:
+    /** Ctor sets end of side 1*/
+    EditAngleMeasureCommand(
+      boost::shared_ptr<AngleMeasureTool>  measureTool,
+      MessageBroker& broker,
+      boost::weak_ptr<ViewportController> controllerW);
+
+    /** This method sets center*/
+    void SetCenter(ScenePoint2D scenePos);
+
+    /** This method sets end of side 1*/
+    void SetSide1End(ScenePoint2D scenePos);
+
+    /** This method sets end of side 2*/
+    void SetSide2End(ScenePoint2D scenePos);
+
+  private:
+    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
+    {
+      return measureTool_;
+    }
+    boost::shared_ptr<AngleMeasureTool> measureTool_;
+  };
+}
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -19,6 +19,7 @@
  **/
 
 #include "EditAngleMeasureTracker.h"
+#include "EditAngleMeasureCommand.h"
 
 namespace OrthancStone
 {
--- a/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h	Fri Oct 04 21:58:30 2019 +0200
@@ -24,6 +24,8 @@
 
 namespace OrthancStone
 {
+  class EditAngleMeasureCommand;
+
   class EditAngleMeasureTracker : public EditMeasureTracker
   {
   public:
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,47 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "EditLineMeasureCommand.h"
+
+namespace OrthancStone
+{
+  EditLineMeasureCommand::EditLineMeasureCommand(
+    boost::shared_ptr<LineMeasureTool>  measureTool,
+    MessageBroker& broker,
+    boost::weak_ptr<ViewportController> controllerW)
+    : EditMeasureCommand(measureTool, controllerW)
+    , measureTool_(measureTool)
+  {
+  }
+
+
+  void EditLineMeasureCommand::SetStart(ScenePoint2D scenePos)
+  {
+    measureTool_->SetStart(scenePos);
+    mementoModified_ = measureTool_->GetMemento();
+  }
+
+
+  void EditLineMeasureCommand::SetEnd(ScenePoint2D scenePos)
+  {
+    measureTool_->SetEnd(scenePos);
+    mementoModified_ = measureTool_->GetMemento();
+  }
+}
--- a/Framework/Scene2DViewport/EditLineMeasureCommand.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureCommand.h	Fri Oct 04 21:58:30 2019 +0200
@@ -0,0 +1,45 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2019 Osimis S.A., 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 "MeasureCommands.h"
+
+namespace OrthancStone
+{
+  class EditLineMeasureCommand : public EditMeasureCommand
+  {
+  public:
+    EditLineMeasureCommand(
+      boost::shared_ptr<LineMeasureTool>  measureTool,
+      MessageBroker& broker,
+      boost::weak_ptr<ViewportController> controllerW);
+
+    void SetStart(ScenePoint2D scenePos);
+    void SetEnd(ScenePoint2D scenePos);
+
+  private:
+    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
+    {
+      return measureTool_;
+    }
+    boost::shared_ptr<LineMeasureTool> measureTool_;
+  };
+}
+
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -19,6 +19,8 @@
  **/
 
 #include "EditLineMeasureTracker.h"
+#include "EditLineMeasureCommand.h"
+
 
 namespace OrthancStone
 {
--- a/Framework/Scene2DViewport/EditLineMeasureTracker.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h	Fri Oct 04 21:58:30 2019 +0200
@@ -24,6 +24,8 @@
 
 namespace OrthancStone
 {
+  class EditLineMeasureCommand;
+
   class EditLineMeasureTracker : public EditMeasureTracker
   {
   public:
--- a/Framework/Scene2DViewport/LineMeasureTool.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -87,6 +87,13 @@
     }
   }
 
+  std::string LineMeasureTool::GetDescription()
+  {
+    std::stringstream ss;
+    ss << "LineMeasureTool. Start = " << start_ << " End = " << end_;
+    return ss.str();
+  }
+
   void LineMeasureTool::ResetHighlightState()
   {
     SetLineHighlightArea(LineHighlightArea_None);
--- a/Framework/Scene2DViewport/LineMeasureTool.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/LineMeasureTool.h	Fri Oct 04 21:58:30 2019 +0200
@@ -53,6 +53,7 @@
     virtual boost::shared_ptr<IFlexiblePointerTracker> CreateEditionTracker(const PointerEvent& e) ORTHANC_OVERRIDE;
     virtual boost::shared_ptr<MeasureToolMemento> GetMemento() const ORTHANC_OVERRIDE;
     virtual void SetMemento(boost::shared_ptr<MeasureToolMemento>) ORTHANC_OVERRIDE;
+    virtual std::string GetDescription() ORTHANC_OVERRIDE;
 
     enum LineHighlightArea
     {
--- a/Framework/Scene2DViewport/MeasureCommands.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureCommands.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -39,7 +39,7 @@
   }
 
   CreateMeasureCommand::CreateMeasureCommand(boost::weak_ptr<ViewportController> controllerW)
-    : TrackerCommand(controllerW)
+    : MeasureCommand(controllerW)
   {
 
   }
@@ -50,8 +50,37 @@
     // we thus leave it as is
   }
 
+  void DeleteMeasureCommand::Redo()
+  {
+    // simply disable the measure tool upon undo
+    GetMeasureTool()->Disable();
+    GetController()->RemoveMeasureTool(GetMeasureTool());
+  }
+
+  void DeleteMeasureCommand::Undo()
+  {
+    GetMeasureTool()->Enable();
+    GetController()->AddMeasureTool(GetMeasureTool());
+  }
+
+  DeleteMeasureCommand::~DeleteMeasureCommand()
+  {
+    // deleting the command should not change the model state
+    // we thus leave it as is
+  }
+
+  DeleteMeasureCommand::DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::weak_ptr<ViewportController> controllerW)
+    : MeasureCommand(controllerW)
+    , measureTool_(measureTool)
+    , mementoOriginal_(measureTool->GetMemento())
+    , mementoModified_(measureTool->GetMemento())
+  {
+    GetMeasureTool()->Disable();
+    GetController()->RemoveMeasureTool(GetMeasureTool());
+  }
+
   EditMeasureCommand::EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::weak_ptr<ViewportController> controllerW)
-    : TrackerCommand(controllerW)
+    : MeasureCommand(controllerW)
     , mementoOriginal_(measureTool->GetMemento())
     , mementoModified_(measureTool->GetMemento())
   {
@@ -74,106 +103,10 @@
     GetMeasureTool()->SetMemento(mementoModified_);
   }
 
-  CreateLineMeasureCommand::CreateLineMeasureCommand(
-    MessageBroker&         broker, 
-    boost::weak_ptr<ViewportController> controllerW,
-    ScenePoint2D           point)
-    : CreateMeasureCommand(controllerW)
-    , measureTool_(
-        boost::make_shared<LineMeasureTool>(boost::ref(broker), controllerW))
-  {
-    GetController()->AddMeasureTool(measureTool_);
-    measureTool_->Set(point, point);
-  }
-
-  void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos)
-  {
-    measureTool_->SetEnd(scenePos);
-  }
-
-  EditLineMeasureCommand::EditLineMeasureCommand(
-    boost::shared_ptr<LineMeasureTool>  measureTool,
-    MessageBroker& broker,
-    boost::weak_ptr<ViewportController> controllerW)
-    : EditMeasureCommand(measureTool,controllerW)
-    , measureTool_(measureTool)
-  {
-  }
-
-
-  void EditLineMeasureCommand::SetStart(ScenePoint2D scenePos)
-  {
-    measureTool_->SetStart(scenePos);
-    mementoModified_ = measureTool_->GetMemento();
-  }
-
-
-  void EditLineMeasureCommand::SetEnd(ScenePoint2D scenePos)
-  {
-    measureTool_->SetEnd(scenePos);
-    mementoModified_ = measureTool_->GetMemento();
-  }
-    
-  CreateAngleMeasureCommand::CreateAngleMeasureCommand(
-    MessageBroker&         broker, 
-    boost::weak_ptr<ViewportController> controllerW,
-    ScenePoint2D           point)
-    : CreateMeasureCommand(controllerW)
-    , measureTool_(
-      boost::make_shared<AngleMeasureTool>(boost::ref(broker), controllerW))
-  {
-    GetController()->AddMeasureTool(measureTool_);
-    measureTool_->SetSide1End(point);
-    measureTool_->SetCenter(point);
-    measureTool_->SetSide2End(point);
-  }
-
-  /** This method sets center*/
-  void CreateAngleMeasureCommand::SetCenter(ScenePoint2D scenePos)
-  {
-    measureTool_->SetCenter(scenePos);
-  }
-
-  /** This method sets end of side 2*/
-  void CreateAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos)
-  {
-    measureTool_->SetSide2End(scenePos);
-  }
-
-  boost::shared_ptr<ViewportController> TrackerCommand::GetController()
+  boost::shared_ptr<ViewportController> MeasureCommand::GetController()
   {
     boost::shared_ptr<ViewportController> controller = controllerW_.lock();
     assert(controller); // accessing dead object?
     return controller;
   }
-
-  EditAngleMeasureCommand::EditAngleMeasureCommand(
-    boost::shared_ptr<AngleMeasureTool>  measureTool,
-    MessageBroker& broker,
-    boost::weak_ptr<ViewportController> controllerW)
-    : EditMeasureCommand(measureTool, controllerW)
-    , measureTool_(measureTool)
-  {
-  }
-
-  void EditAngleMeasureCommand::SetCenter(ScenePoint2D scenePos)
-  {
-    measureTool_->SetCenter(scenePos);
-    mementoModified_ = measureTool_->GetMemento();
-  }
-
-
-  void EditAngleMeasureCommand::SetSide1End(ScenePoint2D scenePos)
-  {
-    measureTool_->SetSide1End(scenePos);
-    mementoModified_ = measureTool_->GetMemento();
-  }
-
-
-  void EditAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos)
-  {
-    measureTool_->SetSide2End(scenePos);
-    mementoModified_ = measureTool_->GetMemento();
-  }
-
 }
--- a/Framework/Scene2DViewport/MeasureCommands.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureCommands.h	Fri Oct 04 21:58:30 2019 +0200
@@ -32,10 +32,10 @@
 
 namespace OrthancStone
 {
-  class TrackerCommand : public boost::noncopyable
+  class MeasureCommand : public boost::noncopyable
   {
   public:
-    TrackerCommand(boost::weak_ptr<ViewportController> controllerW) 
+    MeasureCommand(boost::weak_ptr<ViewportController> controllerW) 
       : controllerW_(controllerW)
     {
 
@@ -43,14 +43,14 @@
     virtual void Undo() = 0;
     virtual void Redo() = 0;
     
-    virtual ~TrackerCommand() {};
+    virtual ~MeasureCommand() {};
 
   protected:
     boost::shared_ptr<ViewportController>  GetController();
     boost::weak_ptr<ViewportController> controllerW_;
   };
 
-  class CreateMeasureCommand : public TrackerCommand
+  class CreateMeasureCommand : public MeasureCommand
   {
   public:
     CreateMeasureCommand(boost::weak_ptr<ViewportController> controllerW);
@@ -62,7 +62,7 @@
     virtual boost::shared_ptr<MeasureTool> GetMeasureTool() = 0;
   };
   
-  class EditMeasureCommand : public TrackerCommand
+  class EditMeasureCommand : public MeasureCommand
   {
   public:
     EditMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::weak_ptr<ViewportController> controllerW);
@@ -83,94 +83,30 @@
     boost::shared_ptr<MeasureToolMemento> mementoModified_;
   };
 
-  class CreateLineMeasureCommand : public CreateMeasureCommand
+  class DeleteMeasureCommand : public MeasureCommand
   {
   public:
-    CreateLineMeasureCommand(
-      MessageBroker&         broker, 
-      boost::weak_ptr<ViewportController> controllerW,
-      ScenePoint2D           point);
-    
-    // the starting position is set in the ctor
-    void SetEnd(ScenePoint2D scenePos);
+    DeleteMeasureCommand(boost::shared_ptr<MeasureTool> measureTool, boost::weak_ptr<ViewportController> controllerW);
+    virtual ~DeleteMeasureCommand();
+    virtual void Undo() ORTHANC_OVERRIDE;
+    virtual void Redo() ORTHANC_OVERRIDE;
+
+    /** This memento is the original object state */
+    boost::shared_ptr<MeasureToolMemento> mementoOriginal_;
 
   private:
-    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
-    {
-      return measureTool_;
-    }
-    boost::shared_ptr<LineMeasureTool> measureTool_;
-  };
-
-
-  class EditLineMeasureCommand : public EditMeasureCommand
-  {
-  public:
-    EditLineMeasureCommand(
-      boost::shared_ptr<LineMeasureTool>  measureTool,
-      MessageBroker&                      broker,
-      boost::weak_ptr<ViewportController> controllerW);
-
-    void SetStart(ScenePoint2D scenePos);
-    void SetEnd(ScenePoint2D scenePos);
-
-  private:
-    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
+    /** Must be implemented by the subclasses that edit the actual tool */
+    virtual boost::shared_ptr<MeasureTool> GetMeasureTool()
     {
       return measureTool_;
     }
-    boost::shared_ptr<LineMeasureTool> measureTool_;
-  };
 
-
-  class CreateAngleMeasureCommand : public CreateMeasureCommand
-  {
-  public:
-    /** Ctor sets end of side 1*/
-    CreateAngleMeasureCommand(
-      MessageBroker&         broker, 
-      boost::weak_ptr<ViewportController> controllerW,
-      ScenePoint2D           point);
-
-    /** This method sets center*/
-    void SetCenter(ScenePoint2D scenePos);
-
-    /** This method sets end of side 2*/
-    void SetSide2End(ScenePoint2D scenePos);
-
-  private:
-    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
-    {
-      return measureTool_;
-    }
-    boost::shared_ptr<AngleMeasureTool> measureTool_;
-  };
+    boost::shared_ptr<MeasureTool> measureTool_;
 
-  class EditAngleMeasureCommand : public EditMeasureCommand
-  {
-  public:
-    /** Ctor sets end of side 1*/
-    EditAngleMeasureCommand(
-      boost::shared_ptr<AngleMeasureTool>  measureTool,
-      MessageBroker& broker,
-      boost::weak_ptr<ViewportController> controllerW);
-
-    /** This method sets center*/
-    void SetCenter(ScenePoint2D scenePos);
+  protected:
 
-    /** This method sets end of side 1*/
-    void SetSide1End(ScenePoint2D scenePos);
-
-    /** This method sets end of side 2*/
-    void SetSide2End(ScenePoint2D scenePos);
-
-  private:
-    virtual boost::shared_ptr<MeasureTool> GetMeasureTool() ORTHANC_OVERRIDE
-    {
-      return measureTool_;
-    }
-    boost::shared_ptr<AngleMeasureTool> measureTool_;
+    /** This memento is updated by the subclasses upon modifications */
+    boost::shared_ptr<MeasureToolMemento> mementoModified_;
   };
-
 }
 
--- a/Framework/Scene2DViewport/MeasureTool.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -30,7 +30,10 @@
 {
   MeasureTool::~MeasureTool()
   {
-    GetController()->Unregister(this);
+    // if the controller is dead, let's not bother.
+    boost::shared_ptr<ViewportController> controller = controllerW_.lock();
+    if (controller)
+      controller->Unregister(this);
   }
 
   void MeasureTool::Enable()
--- a/Framework/Scene2DViewport/MeasureTool.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureTool.h	Fri Oct 04 21:58:30 2019 +0200
@@ -105,6 +105,11 @@
     */
     virtual void ResetHighlightState() = 0;
 
+    /**
+    A description of the measuring tool, useful in debug logs
+    */
+    virtual std::string GetDescription() = 0;
+
   protected:
     MeasureTool(MessageBroker& broker, boost::weak_ptr<ViewportController> controllerW);
 
--- a/Framework/Scene2DViewport/MeasureTrackers.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/MeasureTrackers.h	Fri Oct 04 21:58:30 2019 +0200
@@ -27,6 +27,9 @@
 #include "MeasureTool.h"
 #include "MeasureCommands.h"
 
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
 #include <vector>
 
 namespace OrthancStone
--- a/Framework/Scene2DViewport/PredeclaredTypes.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/PredeclaredTypes.h	Fri Oct 04 21:58:30 2019 +0200
@@ -35,7 +35,7 @@
   class CreateMeasureCommand;
   class CreateLineMeasureCommand;
   class CreateAngleMeasureCommand;
-  class TrackerCommand;
+  class MeasureCommand;
   class ViewportController;
   class LayerHolder;
 }
--- a/Framework/Scene2DViewport/UndoStack.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/UndoStack.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -29,7 +29,7 @@
   UndoStack::UndoStack() : numAppliedCommands_(0)
   {}
 
-  void UndoStack::PushCommand(boost::shared_ptr<TrackerCommand> command)
+  void UndoStack::PushCommand(boost::shared_ptr<MeasureCommand> command)
   {
     commandStack_.erase(
       commandStack_.begin() + numAppliedCommands_,
--- a/Framework/Scene2DViewport/UndoStack.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/UndoStack.h	Fri Oct 04 21:58:30 2019 +0200
@@ -26,7 +26,7 @@
 
 namespace OrthancStone
 {
-  class TrackerCommand;
+  class MeasureCommand;
 
   class UndoStack
   {
@@ -41,7 +41,7 @@
     In other words, when a new command is pushed, all the undone (and not
     redone) commands are removed.
     */
-    void PushCommand(boost::shared_ptr<TrackerCommand> command);
+    void PushCommand(boost::shared_ptr<MeasureCommand> command);
 
     /**
     Undoes the command at the top of the undo stack, or throws if there is no
@@ -64,7 +64,7 @@
     bool CanRedo() const;
   
   private:
-    std::vector<boost::shared_ptr<TrackerCommand> > commandStack_;
+    std::vector<boost::shared_ptr<MeasureCommand> > commandStack_;
 
     /**
     This is always between >= 0 and <= undoStack_.size() and gives the
--- a/Framework/Scene2DViewport/ViewportController.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/ViewportController.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -38,6 +38,11 @@
     , viewport_(viewport)
   {
   }
+ 
+  ViewportController::~ViewportController()
+  {
+
+  }
 
   boost::shared_ptr<UndoStack> ViewportController::GetUndoStack()
   {
@@ -49,7 +54,7 @@
     return undoStackW_.lock();
   }
 
-  void ViewportController::PushCommand(boost::shared_ptr<TrackerCommand> command)
+  void ViewportController::PushCommand(boost::shared_ptr<MeasureCommand> command)
   {
     boost::shared_ptr<UndoStack> undoStack = undoStackW_.lock();
     if(undoStack.get() != NULL)
--- a/Framework/Scene2DViewport/ViewportController.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Scene2DViewport/ViewportController.h	Fri Oct 04 21:58:30 2019 +0200
@@ -84,6 +84,9 @@
                        MessageBroker& broker,
                        IViewport& viewport);
 
+
+    ~ViewportController();
+
     /** 
     This method is called by the GUI system and should update/delete the
     current tracker
@@ -156,7 +159,7 @@
 
 
     /** forwarded to the UndoStack */
-    void PushCommand(boost::shared_ptr<TrackerCommand> command);
+    void PushCommand(boost::shared_ptr<MeasureCommand> command);
 
     /** forwarded to the UndoStack */
     void Undo();
--- a/Framework/Toolbox/AffineTransform2D.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/AffineTransform2D.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -197,6 +197,18 @@
                                                     d.GetHomogeneousMatrix()));
   }
   
+  AffineTransform2D AffineTransform2D::Combine(const AffineTransform2D& a,
+                                               const AffineTransform2D& b,
+                                               const AffineTransform2D& c,
+                                               const AffineTransform2D& d,
+                                               const AffineTransform2D& e)
+  {
+    return AffineTransform2D(LinearAlgebra::Product(a.GetHomogeneousMatrix(),
+                                                    b.GetHomogeneousMatrix(),
+                                                    c.GetHomogeneousMatrix(),
+                                                    d.GetHomogeneousMatrix(),
+                                                    e.GetHomogeneousMatrix()));
+  }
 
   AffineTransform2D AffineTransform2D::CreateOffset(double dx,
                                                     double dy)
--- a/Framework/Toolbox/AffineTransform2D.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/AffineTransform2D.h	Fri Oct 04 21:58:30 2019 +0200
@@ -77,6 +77,12 @@
                                      const AffineTransform2D& c,
                                      const AffineTransform2D& d);
 
+    static AffineTransform2D Combine(const AffineTransform2D& a,
+                                     const AffineTransform2D& b,
+                                     const AffineTransform2D& c,
+                                     const AffineTransform2D& d,
+                                     const AffineTransform2D& e);
+
     static AffineTransform2D CreateOffset(double dx,
                                           double dy);
 
--- a/Framework/Toolbox/CoordinateSystem3D.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/CoordinateSystem3D.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -198,7 +198,6 @@
     offsetY = boost::numeric::ublas::inner_prod(axisY_, projection - origin_);
   }
 
-
   bool CoordinateSystem3D::IntersectSegment(Vector& p,
                                             const Vector& edgeFrom,
                                             const Vector& edgeTo) const
--- a/Framework/Toolbox/DicomStructure2.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructure2.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -18,6 +18,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructure2.h"
 
 #include "../Toolbox/GeometryToolbox.h"
@@ -81,7 +83,7 @@
     }
     if (polygons_.size() < 2)
     {
-      // cannot compute thickness if there are not at least 2 slabs (contours)
+      // cannot compute thickness if there are not at least 2 slabs (structures)
       sliceThickness_ = 1.0;
       state_ = Invalid;
     }
@@ -277,7 +279,7 @@
           // 180.0 / [Math]::Pi = 57.2957795130823
           double acDot = 57.2957795130823 * acos(dot);
           LOG(ERROR) << "DicomStructure2::Project -- cutting plane must be "
-            << "perpendicular to the contours, but dot product is: "
+            << "perpendicular to the structures, but dot product is: "
             << dot << " and (180/pi)*acos(dot) = " << acDot;
           throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
         }
@@ -285,3 +287,7 @@
       return segments.size() != 0;
     }
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/Framework/Toolbox/DicomStructure2.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructure2.h	Fri Oct 04 21:58:30 2019 +0200
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructurePolygon2.h"
 #include "DicomStructureSetUtils.h"
 
@@ -49,7 +51,7 @@
     void ComputeDependentProperties();
 
     /**
-    Being given a plane that is PARALLEL to the set of polygon contours, this 
+    Being given a plane that is PARALLEL to the set of polygon structures, this 
     returns a pointer to the polygon located at that position (if it is closer
     than thickness/2) or NULL if there is none.
 
@@ -153,3 +155,7 @@
     State state_;
   };
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/Framework/Toolbox/DicomStructurePolygon2.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructurePolygon2.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -18,6 +18,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructurePolygon2.h"
 
 #include "../Toolbox/LinearAlgebra.h"
@@ -297,3 +299,7 @@
 
 
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/Framework/Toolbox/DicomStructurePolygon2.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructurePolygon2.h	Fri Oct 04 21:58:30 2019 +0200
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "CoordinateSystem3D.h"
 #include "DicomStructureSetUtils.h"
 #include "Extent2D.h"
@@ -153,3 +155,7 @@
   };
 }
 
+#endif
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
--- a/Framework/Toolbox/DicomStructureSet2.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructureSet2.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -18,6 +18,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructureSet2.h"
 
 #include "../Toolbox/LinearAlgebra.h"
@@ -303,3 +305,7 @@
   }
 
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/Framework/Toolbox/DicomStructureSet2.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Toolbox/DicomStructureSet2.h	Fri Oct 04 21:58:30 2019 +0200
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructure2.h"
 #include "CoordinateSystem3D.h"
 #include "Extent2D.h"
@@ -62,3 +64,8 @@
     std::vector<DicomStructure2> structures_;
   };
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
--- a/Framework/Volumes/DicomStructureSetSlicer2.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Volumes/DicomStructureSetSlicer2.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -18,6 +18,8 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "DicomStructureSetSlicer2.h"
 
 #include "../Toolbox/GeometryToolbox.h"
@@ -107,3 +109,8 @@
   }
 }
 
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
--- a/Framework/Volumes/DicomStructureSetSlicer2.h	Fri Oct 04 21:58:13 2019 +0200
+++ b/Framework/Volumes/DicomStructureSetSlicer2.h	Fri Oct 04 21:58:30 2019 +0200
@@ -21,6 +21,8 @@
 
 #pragma once
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #include "../Toolbox/DicomStructureSet2.h"
 #include "../Volumes/IVolumeSlicer.h"
 
@@ -68,3 +70,7 @@
     boost::weak_ptr<DicomStructureSet2> structureSet_;
   };
 }
+
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
--- a/UnitTestsSources/TestStructureSet.cpp	Fri Oct 04 21:58:13 2019 +0200
+++ b/UnitTestsSources/TestStructureSet.cpp	Fri Oct 04 21:58:30 2019 +0200
@@ -4283,6 +4283,8 @@
 
 #define STONE_ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 static void CheckGroundTruth(
   const std::vector<OrthancStone::DicomStructure2>& structures,
   const size_t structureIndex,
@@ -4295,7 +4297,9 @@
   //double groundTruth[] = { 7.657838, 108.2725, 304.01, 6.826687, 107.4413, 304.01, 6.152492, 106.4785, 304.01, 5.655735, 105.4132, 304.01, 5.351513, 104.2778, 304.01, 5.249068, 103.1069, 304.01, 5.351513, 101.9359, 304.01, 5.655735, 100.8005, 304.01, 6.152492, 99.73524, 304.01, 6.826687, 98.77239, 304.01, 7.657838, 97.94124, 304.01, 8.620689, 97.26704, 304.01, 9.685987, 96.77029, 304.01, 10.82136, 96.46606, 304.01, 11.99231, 96.36362, 304.01, 13.16326, 96.46606, 304.01, 14.29864, 96.77029, 304.01, 15.36393, 97.26704, 304.01, 16.32678, 97.94124, 304.01, 17.15794, 98.77239, 304.01, 17.83213, 99.73524, 304.01, 18.32889, 100.8005, 304.01, 18.63311, 101.9359, 304.01, 18.73555, 103.1069, 304.01, 18.63311, 104.2778, 304.01, 18.32889, 105.4132, 304.01, 17.83213, 106.4785, 304.01, 17.15794, 107.4413, 304.01, 16.32678, 108.2725, 304.01, 15.36393, 108.9467, 304.01, 14.29864, 109.4434, 304.01, 13.16326, 109.7477, 304.01, 11.99231, 109.8501, 304.01, 10.82136, 109.7477, 304.01, 9.685987, 109.4434, 304.01, 8.620689, 108.9467, 304.01 };
   size_t groundTruthItems = groundTruth.size();
 
-  EXPECT_EQ(groundTruthItems, 3 * polygon.GetPointCount());
+  size_t pointCount = 3 * polygon.GetPointCount();
+
+  EXPECT_EQ(groundTruthItems, pointCount);
 
   for (size_t i = 0; i < polygon.GetPointCount(); ++i)
   {
@@ -4313,7 +4317,6 @@
 }
 
 
-
 TEST(StructureSet, ReadFromJsonThatsAll)
 {
   DicomStructureSet2 structureSet;
@@ -4391,32 +4394,32 @@
 
   {
     double groundTruthRaw[] = { 7.657838, 108.2725, 304.01, 6.826687, 107.4413, 304.01, 6.152492, 106.4785, 304.01, 5.655735, 105.4132, 304.01, 5.351513, 104.2778, 304.01, 5.249068, 103.1069, 304.01, 5.351513, 101.9359, 304.01, 5.655735, 100.8005, 304.01, 6.152492, 99.73524, 304.01, 6.826687, 98.77239, 304.01, 7.657838, 97.94124, 304.01, 8.620689, 97.26704, 304.01, 9.685987, 96.77029, 304.01, 10.82136, 96.46606, 304.01, 11.99231, 96.36362, 304.01, 13.16326, 96.46606, 304.01, 14.29864, 96.77029, 304.01, 15.36393, 97.26704, 304.01, 16.32678, 97.94124, 304.01, 17.15794, 98.77239, 304.01, 17.83213, 99.73524, 304.01, 18.32889, 100.8005, 304.01, 18.63311, 101.9359, 304.01, 18.73555, 103.1069, 304.01, 18.63311, 104.2778, 304.01, 18.32889, 105.4132, 304.01, 17.83213, 106.4785, 304.01, 17.15794, 107.4413, 304.01, 16.32678, 108.2725, 304.01, 15.36393, 108.9467, 304.01, 14.29864, 109.4434, 304.01, 13.16326, 109.7477, 304.01, 11.99231, 109.8501, 304.01, 10.82136, 109.7477, 304.01, 9.685987, 109.4434, 304.01, 8.620689, 108.9467, 304.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     CheckGroundTruth(structures, 0, 0, groundTruth);
   }
   {
     double groundTruthRaw[] = { 7.657838, 108.2725, 310.01, 6.826687, 107.4413, 310.01, 6.152492, 106.4785, 310.01, 5.655735, 105.4132, 310.01, 5.351513, 104.2778, 310.01, 5.249068, 103.1069, 310.01, 5.351513, 101.9359, 310.01, 5.655735, 100.8005, 310.01, 6.152492, 99.73524, 310.01, 6.826687, 98.77239, 310.01, 7.657838, 97.94124, 310.01, 8.620689, 97.26704, 310.01, 9.685987, 96.77029, 310.01, 10.82136, 96.46606, 310.01, 11.99231, 96.36362, 310.01, 13.16326, 96.46606, 310.01, 14.29864, 96.77029, 310.01, 15.36393, 97.26704, 310.01, 16.32678, 97.94124, 310.01, 17.15794, 98.77239, 310.01, 17.83213, 99.73524, 310.01, 18.32889, 100.8005, 310.01, 18.63311, 101.9359, 310.01, 18.73555, 103.1069, 310.01, 18.63311, 104.2778, 310.01, 18.32889, 105.4132, 310.01, 17.83213, 106.4785, 310.01, 17.15794, 107.4413, 310.01, 16.32678, 108.2725, 310.01, 15.36393, 108.9467, 310.01, 14.29864, 109.4434, 310.01, 13.16326, 109.7477, 310.01, 11.99231, 109.8501, 310.01, 10.82136, 109.7477, 310.01, 9.685987, 109.4434, 310.01, 8.620689, 108.9467, 310.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     CheckGroundTruth(structures, 0, 2, groundTruth);
   }
   {
     double groundTruthRaw[] = { -37.967, 161.9664, 304.01, -39.10237, 161.6622, 304.01, -40.16767, 161.1655, 304.01, -41.13052, 160.4913, 304.01, -41.96167, 159.6601, 304.01, -42.63587, 158.6973, 304.01, -43.13263, 157.632, 304.01, -43.43685, 156.4966, 304.01, -43.53929, 155.3257, 304.01, -43.43685, 154.1547, 304.01, -43.13263, 153.0193, 304.01, -42.63587, 151.954, 304.01, -41.96167, 150.9912, 304.01, -41.13052, 150.16, 304.01, -40.16767, 149.4858, 304.01, -39.10237, 148.9891, 304.01, -37.967, 148.6849, 304.01, -36.79605, 148.5824, 304.01, -35.6251, 148.6849, 304.01, -34.48972, 148.9891, 304.01, -33.42443, 149.4858, 304.01, -32.46157, 150.16, 304.01, -31.63042, 150.9912, 304.01, -30.95623, 151.954, 304.01, -30.45947, 153.0193, 304.01, -30.15525, 154.1547, 304.01, -30.0528, 155.3257, 304.01, -30.15525, 156.4966, 304.01, -30.45947, 157.632, 304.01, -30.95623, 158.6973, 304.01, -31.63042, 159.6601, 304.01, -32.46157, 160.4913, 304.01, -33.42443, 161.1655, 304.01, -34.48972, 161.6622, 304.01, -35.6251, 161.9664, 304.01, -36.79605, 162.0689, 304.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     CheckGroundTruth(structures, 1, 0, groundTruth);
   }
   {
     double groundTruthRaw[] = { 69.4042, 150.7324, 307.01, 69.70842, 151.8678, 307.01, 69.81087, 153.0387, 307.01, 69.70842, 154.2097, 307.01, 69.4042, 155.345, 307.01, 68.90745, 156.4103, 307.01, 68.23325, 157.3732, 307.01, 67.4021, 158.2043, 307.01, 66.43925, 158.8785, 307.01, 65.37395, 159.3753, 307.01, 64.23858, 159.6795, 307.01, 63.06762, 159.7819, 307.01, 61.89667, 159.6795, 307.01, 60.7613, 159.3753, 307.01, 59.696, 158.8785, 307.01, 58.73315, 158.2043, 307.01, 57.902, 157.3732, 307.01, 57.22781, 156.4103, 307.01, 56.73105, 155.345, 307.01, 56.42683, 154.2097, 307.01, 56.32438, 153.0387, 307.01, 56.42683, 151.8678, 307.01, 56.73105, 150.7324, 307.01, 57.22781, 149.6671, 307.01, 57.902, 148.7042, 307.01, 58.73315, 147.8731, 307.01, 59.696, 147.1989, 307.01, 60.7613, 146.7021, 307.01, 61.89667, 146.3979, 307.01, 63.06762, 146.2955, 307.01, 64.23858, 146.3979, 307.01, 65.37395, 146.7021, 307.01, 66.43925, 147.1989, 307.01, 67.4021, 147.8731, 307.01, 68.23325, 148.7042, 307.01, 68.90745, 149.6671, 307.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     CheckGroundTruth(structures, 2, 1, groundTruth);
   }
 
   {
     double groundTruthRaw[] = { 108.3984, 232.7406, 274.01, 106.0547, 231.7948, 274.01, 103.7109, 232.8407, 274.01, 96.67969, 232.8757, 274.01, 77.92969, 232.887, 274.01, 47.46094, 232.8902, 274.01, 38.08594, 232.7537, 274.01, 37.6668, 232.3734, 274.01, 38.08594, 231.9774, 274.01, 40.42969, 231.8475, 274.01, 41.76413, 230.0297, 274.01, 42.77344, 229.1388, 274.01, 45.11719, 228.5069, 274.01, 47.46094, 227.1533, 274.01, 49.80469, 226.3505, 274.01, 52.14844, 224.6564, 274.01, 54.49219, 223.923, 274.01, 56.83594, 222.0692, 274.01, 59.17969, 220.3438, 274.01, 61.52344, 219.3888, 274.01, 63.86719, 217.1287, 274.01, 65.83488, 215.9672, 274.01, 68.55469, 213.2383, 274.01, 70.89844, 211.2328, 274.01, 72.8125, 208.9359, 274.01, 75.58594, 206.3615, 274.01, 76.91445, 204.2484, 274.01, 78.89509, 201.9047, 274.01, 80.51276, 199.5609, 274.01, 81.51955, 197.2172, 274.01, 83.67448, 194.8734, 274.01, 84.60938, 192.5297, 274.01, 85.86986, 190.1859, 274.01, 86.57623, 187.8422, 274.01, 88.30051, 185.4984, 274.01, 88.94002, 183.1547, 274.01, 89.23261, 180.8109, 274.01, 89.64844, 180.3263, 274.01, 90.71885, 178.4672, 274.01, 90.97656, 176.1234, 274.01, 91.99219, 174.4794, 274.01, 92.56773, 173.7797, 274.01, 92.80016, 171.4359, 274.01, 93.23473, 169.0922, 274.01, 93.37606, 166.7484, 274.01, 93.60748, 157.3734, 274.01, 93.6341, 152.6859, 274.01, 93.35742, 140.9672, 274.01, 92.89317, 138.6234, 274.01, 92.7069, 136.2797, 274.01, 92.03726, 133.9359, 274.01, 90.84009, 131.5922, 274.01, 90.3769, 129.2484, 274.01, 89.09074, 126.9047, 274.01, 88.13225, 122.2172, 274.01, 86.17828, 119.8734, 274.01, 84.96094, 117.4163, 274.01, 83.99619, 115.1859, 274.01, 83.13079, 112.8422, 274.01, 82.61719, 112.2984, 274.01, 80.27344, 108.8454, 274.01, 79.64514, 108.1547, 274.01, 77.21497, 105.8109, 274.01, 76.47787, 103.4672, 274.01, 75.58594, 102.6177, 274.01, 73.24219, 100.0077, 274.01, 69.54492, 96.43594, 274.01, 67.34096, 94.09219, 274.01, 64.66306, 91.74844, 274.01, 63.86719, 90.92619, 274.01, 61.52344, 90.20454, 274.01, 59.17969, 87.78574, 274.01, 56.83594, 86.48566, 274.01, 54.49219, 84.31388, 274.01, 52.14844, 83.44438, 274.01, 49.80469, 82.75121, 274.01, 49.37617, 82.37344, 274.01, 47.46094, 81.26244, 274.01, 45.71391, 80.02969, 274.01, 45.11719, 79.45415, 274.01, 42.77344, 79.08185, 274.01, 40.42969, 78.51941, 274.01, 38.08594, 78.27534, 274.01, 37.36932, 77.68594, 274.01, 35.74219, 76.67624, 274.01, 33.39844, 76.49941, 274.01, 31.05469, 76.03495, 274.01, 28.71094, 74.83174, 274.01, 26.36719, 74.62859, 274.01, 24.02344, 74.55463, 274.01, 21.67969, 74.22861, 274.01, 19.33594, 74.05312, 274.01, 12.30469, 73.99397, 274.01, 5.273438, 74.0736, 274.01, 2.929688, 74.55463, 274.01, 0.5859375, 74.68513, 274.01, -1.757813, 74.914, 274.01, -2.319131, 75.34219, 274.01, -4.101563, 76.31516, 274.01, -8.789063, 76.74514, 274.01, -11.13281, 78.39038, 274.01, -13.47656, 78.6124, 274.01, -15.82031, 79.19784, 274.01, -18.16406, 81.11024, 274.01, -20.50781, 82.03296, 274.01, -22.85156, 83.13991, 274.01, -25.19531, 83.70732, 274.01, -27.53906, 85.85863, 274.01, -29.88281, 87.03368, 274.01, -32.22656, 88.3274, 274.01, -34.57031, 90.53674, 274.01, -36.91406, 92.5602, 274.01, -39.25781, 93.55952, 274.01, -41.60156, 95.74537, 274.01, -43.94531, 98.26609, 274.01, -46.28906, 100.3701, 274.01, -47.02621, 101.1234, 274.01, -47.86611, 103.4672, 274.01, -49.83594, 105.8109, 274.01, -51.98182, 108.1547, 274.01, -53.06448, 110.4984, 274.01, -53.32031, 110.7675, 274.01, -54.53804, 112.8422, 274.01, -55.66406, 114.273, 274.01, -56.55722, 115.1859, 274.01, -57.13953, 117.5297, 274.01, -58.29264, 119.8734, 274.01, -59.26869, 122.2172, 274.01, -60.35156, 124.0119, 274.01, -60.84229, 124.5609, 274.01, -61.54484, 126.9047, 274.01, -61.71691, 129.2484, 274.01, -63.62281, 131.5922, 274.01, -63.81256, 133.9359, 274.01, -64.12511, 136.2797, 274.01, -64.84515, 138.6234, 274.01, -65.13599, 140.9672, 274.01, -65.33604, 143.3109, 274.01, -65.87358, 145.6547, 274.01, -66.10577, 147.9984, 274.01, -66.17618, 155.0297, 274.01, -66.09933, 162.0609, 274.01, -65.40382, 164.4047, 274.01, -65.24833, 166.7484, 274.01, -64.71442, 171.4359, 274.01, -63.88171, 173.7797, 274.01, -63.69299, 176.1234, 274.01, -61.79081, 178.4672, 274.01, -61.59269, 180.8109, 274.01, -61.19405, 183.1547, 274.01, -60.35156, 185.2055, 274.01, -59.08288, 187.8422, 274.01, -58.00781, 189.3499, 274.01, -57.25858, 190.1859, 274.01, -56.64558, 192.5297, 274.01, -55.29191, 194.8734, 274.01, -54.28698, 197.2172, 274.01, -52.28595, 199.5609, 274.01, -51.47569, 201.9047, 274.01, -48.63281, 204.6417, 274.01, -47.10181, 206.5922, 274.01, -44.64154, 208.9359, 274.01, -42.38504, 211.2797, 274.01, -39.25781, 214.4025, 274.01, -37.42723, 215.9672, 274.01, -34.57031, 218.9107, 274.01, -32.22656, 219.7277, 274.01, -29.88281, 221.6934, 274.01, -27.53906, 222.852, 274.01, -25.19531, 224.5168, 274.01, -22.85156, 225.9419, 274.01, -20.50781, 226.7359, 274.01, -18.16406, 228.3332, 274.01, -15.82031, 229.065, 274.01, -13.47656, 229.267, 274.01, -12.63854, 230.0297, 274.01, -11.13281, 231.9201, 274.01, -10.65505, 232.3734, 274.01, -11.13281, 232.7794, 274.01, -15.82031, 232.792, 274.01, -18.16406, 232.8902, 274.01, -36.91406, 232.9015, 274.01, -39.25781, 232.8902, 274.01, -50.97656, 232.9236, 274.01, -60.35156, 232.9126, 274.01, -67.38281, 232.8407, 274.01, -72.07031, 232.8642, 274.01, -79.10156, 232.8555, 274.01, -83.78906, 232.8788, 274.01, -95.50781, 232.8902, 274.01, -97.85156, 233.4886, 274.01, -100.1953, 233.647, 274.01, -102.5391, 232.9858, 274.01, -104.8828, 233.6969, 274.01, -109.5703, 233.722, 274.01, -125.9766, 233.7086, 274.01, -128.3203, 233.2849, 274.01, -130.6641, 233.702, 274.01, -135.3516, 233.727, 274.01, -149.4141, 233.7135, 274.01, -156.4453, 233.727, 274.01, -163.4766, 233.7119, 274.01, -168.1641, 233.7643, 274.01, -191.6016, 233.7809, 274.01, -210.3516, 233.7716, 274.01, -224.4141, 233.7998, 274.01, -233.7891, 233.7647, 274.01, -243.1641, 233.7785, 274.01, -247.8516, 233.7378, 274.01, -254.8828, 233.8578, 274.01, -257.2266, 235.2519, 274.01, -259.5703, 236.0817, 274.01, -260.7617, 237.0609, 274.01, -261.9141, 238.2262, 274.01, -262.8989, 239.4047, 274.01, -262.9743, 241.7484, 274.01, -262.5977, 244.0922, 274.01, -260.6675, 246.4359, 274.01, -259.6161, 248.7797, 274.01, -257.2266, 251.0035, 274.01, -255.0361, 253.4672, 274.01, -252.5391, 256.0995, 274.01, -251.2277, 258.1547, 274.01, -246.7444, 262.8422, 274.01, -243.1641, 266.3515, 274.01, -239.7411, 269.8734, 274.01, -238.4766, 270.9495, 274.01, -237.2269, 272.2172, 274.01, -236.1328, 273.5215, 274.01, -235.0934, 274.5609, 274.01, -233.7891, 275.6655, 274.01, -232.5319, 276.9047, 274.01, -231.4453, 278.1693, 274.01, -227.917, 281.5922, 274.01, -224.4141, 285.1802, 274.01, -222.0703, 287.4025, 274.01, -218.6841, 290.9672, 274.01, -217.3828, 291.9709, 274.01, -215.0391, 293.1788, 274.01, -212.6953, 294.5138, 274.01, -210.3516, 295.2614, 274.01, -209.8994, 295.6547, 274.01, -208.0078, 296.7083, 274.01, -203.3203, 296.9372, 274.01, -196.2891, 296.9317, 274.01, -193.9453, 296.8988, 274.01, -172.8516, 296.8482, 274.01, -161.1328, 296.843, 274.01, -137.6953, 296.8542, 274.01, -130.6641, 296.8378, 274.01, -107.2266, 296.8379, 274.01, -93.16406, 296.8208, 274.01, -74.41406, 296.838, 274.01, -65.03906, 296.8609, 274.01, -50.97656, 296.8556, 274.01, -46.28906, 296.9051, 274.01, -41.60156, 298.5331, 274.01, -39.25781, 298.5624, 274.01, -36.91406, 297.1455, 274.01, -34.57031, 297.0498, 274.01, -32.22656, 298.5589, 274.01, -25.19531, 298.5624, 274.01, -22.85156, 297.2842, 274.01, -20.50781, 298.5624, 274.01, -1.757813, 298.5624, 274.01, 0.5859375, 297.2104, 274.01, 2.929688, 298.5624, 274.01, 5.273438, 297.6946, 274.01, 7.617188, 298.5168, 274.01, 9.960938, 298.5512, 274.01, 12.30469, 296.937, 274.01, 14.64844, 298.5478, 274.01, 16.99219, 298.5478, 274.01, 19.33594, 297.0782, 274.01, 21.67969, 296.844, 274.01, 23.54531, 297.9984, 274.01, 24.02344, 298.4023, 274.01, 24.50156, 297.9984, 274.01, 26.36719, 296.844, 274.01, 38.08594, 296.8381, 274.01, 52.14844, 296.8033, 274.01, 59.17969, 296.8033, 274.01, 73.24219, 296.7682, 274.01, 99.02344, 296.7566, 274.01, 117.7734, 296.7216, 274.01, 129.4922, 296.7152, 274.01, 131.8359, 295.9083, 274.01, 134.1797, 295.5245, 274.01, 138.8672, 295.4763, 274.01, 155.2734, 295.4763, 274.01, 176.3672, 295.3861, 274.01, 190.4297, 295.3718, 274.01, 197.4609, 295.4763, 274.01, 202.1484, 295.4454, 274.01, 204.4922, 295.3438, 274.01, 206.8359, 295.0757, 274.01, 209.1797, 294.4124, 274.01, 211.5234, 292.3133, 274.01, 213.8672, 291.0809, 274.01, 216.2109, 289.6743, 274.01, 217.3081, 288.6234, 274.01, 219.3558, 286.2797, 274.01, 221.8608, 283.9359, 274.01, 225.5859, 280.045, 274.01, 227.9297, 277.8885, 274.01, 230.2734, 275.2857, 274.01, 232.6172, 273.2225, 274.01, 233.6225, 272.2172, 274.01, 234.9609, 270.5822, 274.01, 238.2254, 267.5297, 274.01, 240.3691, 265.1859, 274.01, 244.3359, 261.3326, 274.01, 246.6797, 258.8034, 274.01, 249.0234, 256.7196, 274.01, 251.3672, 254.0746, 274.01, 254.5313, 251.1234, 274.01, 255.333, 248.7797, 274.01, 257.3723, 246.4359, 274.01, 259.7201, 244.0922, 274.01, 260.106, 241.7484, 274.01, 261.6423, 239.4047, 274.01, 261.0804, 237.0609, 274.01, 259.3552, 234.7172, 274.01, 258.3984, 233.7696, 274.01, 256.0547, 232.8757, 274.01, 253.7109, 232.792, 274.01, 251.3672, 232.8161, 274.01, 246.6797, 232.6981, 274.01, 244.3359, 232.725, 274.01, 239.6484, 232.9137, 274.01, 234.9609, 232.8525, 274.01, 225.5859, 232.8757, 274.01, 209.1797, 232.8757, 274.01, 204.4922, 232.7537, 274.01, 195.1172, 232.7794, 274.01, 171.6797, 232.792, 274.01, 164.6484, 232.7666, 274.01, 152.9297, 232.7666, 274.01, 148.2422, 232.792, 274.01, 138.8672, 232.7406, 274.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     EXPECT_EQ(340u * 3, groundTruth.size());
     CheckGroundTruth(structures, 5, 0, groundTruth);
@@ -4424,13 +4427,16 @@
 
   {
     double groundTruthRaw[] = { -18.16406, 233.0632, 298.01, -27.53906, 233.1042, 298.01, -29.88281, 233.0819, 298.01, -34.57031, 233.131, 298.01, -43.94531, 233.1221, 298.01, -50.97656, 233.1736, 298.01, -62.69531, 233.1397, 298.01, -65.03906, 232.8376, 298.01, -69.72656, 232.9839, 298.01, -79.10156, 233.0245, 298.01, -90.82031, 233.0382, 298.01, -93.16406, 233.0859, 298.01, -109.5703, 233.1132, 298.01, -111.9141, 233.1791, 298.01, -114.2578, 233.7139, 298.01, -118.9453, 233.9793, 298.01, -128.3203, 234.0284, 298.01, -130.6641, 233.9793, 298.01, -135.3516, 234.0591, 298.01, -137.6953, 234.0284, 298.01, -142.3828, 234.0855, 298.01, -144.7266, 234.0284, 298.01, -151.7578, 234.002, 298.01, -158.7891, 234.0263, 298.01, -163.4766, 233.9784, 298.01, -165.8203, 234.0072, 298.01, -168.1641, 234.1756, 298.01, -170.5078, 234.2214, 298.01, -179.8828, 234.1934, 298.01, -186.9141, 234.2721, 298.01, -189.2578, 234.2289, 298.01, -193.9453, 234.2431, 298.01, -198.6328, 234.1692, 298.01, -200.9766, 234.2326, 298.01, -205.6641, 234.1271, 298.01, -212.6953, 234.2224, 298.01, -215.0391, 234.1992, 298.01, -222.0703, 234.3115, 298.01, -224.4141, 234.2224, 298.01, -226.7578, 234.2502, 298.01, -233.7891, 234.0906, 298.01, -238.4766, 234.0329, 298.01, -243.1641, 234.0283, 298.01, -247.8516, 233.7949, 298.01, -250.1953, 233.8681, 298.01, -252.5391, 234.7626, 298.01, -254.3469, 237.0609, 298.01, -255.6034, 239.4047, 298.01, -254.5181, 241.7484, 298.01, -254.2274, 244.0922, 298.01, -254.181, 248.7797, 298.01, -253.9355, 251.1234, 298.01, -253.5926, 253.4672, 298.01, -252.7483, 255.8109, 298.01, -250.8092, 258.1547, 298.01, -248.713, 260.4984, 298.01, -246.263, 262.8422, 298.01, -244.1406, 265.1859, 298.01, -241.6671, 267.5297, 298.01, -239.4754, 269.8734, 298.01, -237.0156, 272.2172, 298.01, -233.7891, 275.382, 298.01, -231.4453, 277.8249, 298.01, -229.1016, 279.9981, 298.01, -226.7578, 282.5281, 298.01, -224.4141, 284.6784, 298.01, -222.0703, 287.2355, 298.01, -220.5414, 288.6234, 298.01, -218.2745, 290.9672, 298.01, -217.3828, 291.6508, 298.01, -212.6953, 294.5949, 298.01, -210.3516, 295.3142, 298.01, -208.0078, 296.4674, 298.01, -205.6641, 296.8852, 298.01, -203.3203, 297.1563, 298.01, -196.2891, 297.1488, 298.01, -193.9453, 297.0597, 298.01, -182.2266, 296.9529, 298.01, -168.1641, 296.8576, 298.01, -154.1016, 296.9249, 298.01, -149.4141, 296.8921, 298.01, -128.3203, 296.9228, 298.01, -121.2891, 296.8623, 298.01, -111.9141, 296.8549, 298.01, -107.2266, 296.8266, 298.01, -102.5391, 296.8731, 298.01, -95.50781, 296.8453, 298.01, -88.47656, 296.9218, 298.01, -83.78906, 296.9016, 298.01, -69.72656, 296.979, 298.01, -67.38281, 296.9514, 298.01, -65.03906, 297.2199, 298.01, -62.69531, 296.9622, 298.01, -55.66406, 296.9926, 298.01, -50.97656, 296.9467, 298.01, -48.63281, 297.3652, 298.01, -46.28906, 297.0439, 298.01, -43.94531, 297.2875, 298.01, -39.25781, 297.0121, 298.01, -34.57031, 297.1564, 298.01, -32.22656, 297.3612, 298.01, -29.88281, 297.4229, 298.01, -27.53906, 297.1687, 298.01, -25.19531, 297.4334, 298.01, -18.16406, 297.3612, 298.01, -15.82031, 297.4441, 298.01, -13.47656, 297.4125, 298.01, -11.13281, 297.2468, 298.01, -8.789063, 297.4125, 298.01, -6.445313, 297.373, 298.01, -4.101563, 297.4195, 298.01, -1.757813, 297.077, 298.01, 0.5859375, 297.4229, 298.01, 2.929688, 297.4125, 298.01, 5.273438, 296.9489, 298.01, 7.617188, 297.3168, 298.01, 9.960938, 296.9377, 298.01, 12.30469, 296.8998, 298.01, 14.64844, 297.1975, 298.01, 16.99219, 296.8579, 298.01, 28.71094, 296.878, 298.01, 40.42969, 296.8163, 298.01, 42.77344, 296.8369, 298.01, 49.80469, 296.734, 298.01, 59.17969, 296.6906, 298.01, 61.52344, 296.6365, 298.01, 68.55469, 296.6278, 298.01, 73.24219, 296.5777, 298.01, 75.58594, 296.6191, 298.01, 84.96094, 296.5284, 298.01, 96.67969, 296.5538, 298.01, 103.7109, 296.479, 298.01, 115.4297, 296.4259, 298.01, 122.4609, 296.3434, 298.01, 129.4922, 296.3495, 298.01, 131.8359, 295.9141, 298.01, 136.5234, 296.2256, 298.01, 138.8672, 295.833, 298.01, 143.5547, 295.9857, 298.01, 145.8984, 295.8791, 298.01, 152.9297, 295.833, 298.01, 164.6484, 295.6819, 298.01, 171.6797, 295.6819, 298.01, 181.0547, 295.5401, 298.01, 185.7422, 295.5742, 298.01, 192.7734, 295.557, 298.01, 197.4609, 295.8012, 298.01, 202.1484, 295.6819, 298.01, 204.4922, 295.3698, 298.01, 206.8359, 294.803, 298.01, 209.1797, 294.3656, 298.01, 211.5234, 292.4764, 298.01, 213.8672, 291.1765, 298.01, 216.2109, 289.5873, 298.01, 217.229, 288.6234, 298.01, 218.5547, 287.0752, 298.01, 221.7097, 283.9359, 298.01, 225.5859, 279.8775, 298.01, 227.9297, 277.5633, 298.01, 230.2734, 275.0808, 298.01, 233.1989, 272.2172, 298.01, 234.9609, 270.2887, 298.01, 237.7384, 267.5297, 298.01, 241.9922, 263.0843, 298.01, 244.3359, 260.7643, 298.01, 246.788, 258.1547, 298.01, 249.0234, 255.451, 298.01, 250.3651, 253.4672, 298.01, 251.5297, 251.1234, 298.01, 252.1947, 248.7797, 298.01, 252.4915, 246.4359, 298.01, 252.5755, 241.7484, 298.01, 252.8592, 239.4047, 298.01, 252.9236, 237.0609, 298.01, 252.2924, 234.7172, 298.01, 251.3672, 233.4697, 298.01, 249.0234, 232.882, 298.01, 244.3359, 232.9048, 298.01, 241.9922, 233.0145, 298.01, 232.6172, 232.9048, 298.01, 227.9297, 233.0007, 298.01, 216.2109, 233.0632, 298.01, 211.5234, 233.0537, 298.01, 206.8359, 232.9699, 298.01, 204.4922, 232.7322, 298.01, 199.8047, 232.7186, 298.01, 190.4297, 232.7719, 298.01, 183.3984, 232.7719, 298.01, 181.0547, 232.7322, 298.01, 174.0234, 232.7048, 298.01, 171.6797, 232.7322, 298.01, 166.9922, 232.6908, 298.01, 157.6172, 232.7975, 298.01, 155.2734, 232.7588, 298.01, 148.2422, 232.7875, 298.01, 143.5547, 232.7614, 298.01, 138.8672, 232.6477, 298.01, 124.8047, 232.6179, 298.01, 122.4609, 232.6477, 298.01, 113.0859, 232.6027, 298.01, 110.7422, 232.4552, 298.01, 108.3984, 232.2192, 298.01, 106.0547, 231.6764, 298.01, 103.7109, 231.8559, 298.01, 102.8237, 232.3734, 298.01, 101.3672, 232.9839, 298.01, 99.02344, 233.0951, 298.01, 87.30469, 233.0819, 298.01, 84.96094, 233.1091, 298.01, 80.27344, 233.0726, 298.01, 77.92969, 233.1132, 298.01, 70.89844, 233.1397, 298.01, 68.55469, 233.1132, 298.01, 52.14844, 233.131, 298.01, 45.11719, 233.0859, 298.01, 44.16726, 232.3734, 298.01, 42.77344, 231.0206, 298.01, 42.04498, 230.0297, 298.01, 42.77344, 229.2462, 298.01, 45.11719, 228.5664, 298.01, 47.46094, 227.0695, 298.01, 49.80469, 226.0552, 298.01, 52.14844, 224.5723, 298.01, 54.49219, 223.6857, 298.01, 56.83594, 221.8519, 298.01, 59.17969, 220.2086, 298.01, 61.52344, 218.8854, 298.01, 64.94469, 215.9672, 298.01, 66.21094, 215.0191, 298.01, 67.72036, 213.6234, 298.01, 68.55469, 212.6986, 298.01, 70.89844, 210.5055, 298.01, 74.53191, 206.5922, 298.01, 76.54903, 204.2484, 298.01, 78.26105, 201.9047, 298.01, 80.27344, 198.9262, 298.01, 82.61719, 195.2822, 298.01, 82.98087, 194.8734, 298.01, 84.96094, 190.9255, 298.01, 85.43701, 190.1859, 298.01, 86.33423, 187.8422, 298.01, 87.78722, 185.4984, 298.01, 88.60233, 183.1547, 298.01, 89.10253, 180.8109, 298.01, 90.17504, 178.4672, 298.01, 90.88959, 176.1234, 298.01, 91.43783, 173.7797, 298.01, 92.39601, 171.4359, 298.01, 92.95762, 169.0922, 298.01, 93.55695, 159.7172, 298.01, 93.65527, 157.3734, 298.01, 93.67542, 152.6859, 298.01, 93.61213, 150.3422, 298.01, 93.22542, 143.3109, 298.01, 93.06345, 140.9672, 298.01, 92.77563, 138.6234, 298.01, 91.21714, 133.9359, 298.01, 90.67235, 131.5922, 298.01, 89.88776, 129.2484, 298.01, 88.8737, 126.9047, 298.01, 88.44087, 124.5609, 298.01, 86.09712, 119.8734, 298.01, 85.05786, 117.5297, 298.01, 83.87151, 115.1859, 298.01, 82.22388, 112.8422, 298.01, 81.09117, 110.4984, 298.01, 77.92969, 106.4052, 298.01, 77.3894, 105.8109, 298.01, 75.94332, 103.4672, 298.01, 71.71799, 98.77969, 298.01, 68.55469, 95.65721, 298.01, 63.86719, 91.54878, 298.01, 61.52344, 90.1121, 298.01, 59.17969, 88.15762, 298.01, 56.83594, 86.51503, 298.01, 54.49219, 85.42721, 298.01, 52.14844, 83.64907, 298.01, 49.80469, 82.89023, 298.01, 47.46094, 81.50237, 298.01, 45.11719, 80.62591, 298.01, 42.77344, 79.18153, 298.01, 40.42969, 78.7203, 298.01, 38.08594, 78.1349, 298.01, 35.74219, 77.11755, 298.01, 33.39844, 76.51949, 298.01, 31.05469, 76.07934, 298.01, 26.36719, 74.67744, 298.01, 24.02344, 74.42056, 298.01, 14.64844, 74.07317, 298.01, 9.960938, 74.11538, 298.01, 2.929688, 74.40105, 298.01, 0.5859375, 74.67952, 298.01, -1.757813, 75.31406, 298.01, -4.101563, 76.07065, 298.01, -6.445313, 76.49051, 298.01, -8.789063, 77.17276, 298.01, -11.13281, 78.20097, 298.01, -15.82031, 79.31967, 298.01, -18.16406, 80.76948, 298.01, -20.50781, 81.64266, 298.01, -22.85156, 83.0305, 298.01, -25.19531, 83.7937, 298.01, -27.53906, 85.63515, 298.01, -29.88281, 86.7363, 298.01, -32.22656, 88.36089, 298.01, -34.57031, 90.3302, 298.01, -36.56719, 91.74844, 298.01, -41.60156, 95.93605, 298.01, -46.58845, 101.1234, 298.01, -50.17995, 105.8109, 298.01, -52.10386, 108.1547, 298.01, -53.63992, 110.4984, 298.01, -54.95532, 112.8422, 298.01, -56.64794, 115.1859, 298.01, -57.4403, 117.5297, 298.01, -58.91927, 119.8734, 298.01, -59.78655, 122.2172, 298.01, -61.11754, 124.5609, 298.01, -61.58921, 126.9047, 298.01, -62.38012, 129.2484, 298.01, -63.49118, 131.5922, 298.01, -64.02599, 133.9359, 298.01, -64.3932, 136.2797, 298.01, -65.11897, 138.6234, 298.01, -65.64544, 140.9672, 298.01, -66.23938, 147.9984, 298.01, -66.46289, 152.6859, 298.01, -66.48911, 155.0297, 298.01, -66.34437, 159.7172, 298.01, -65.99894, 164.4047, 298.01, -65.49149, 169.0922, 298.01, -64.6875, 171.4359, 298.01, -63.7739, 176.1234, 298.01, -62.9398, 178.4672, 298.01, -61.86011, 180.8109, 298.01, -61.33423, 183.1547, 298.01, -60.43332, 185.4984, 298.01, -58.00781, 190.0632, 298.01, -56.85406, 192.5297, 298.01, -55.66406, 194.7283, 298.01, -54.11692, 197.2172, 298.01, -50.97656, 201.8369, 298.01, -47.36435, 206.5922, 298.01, -45.04395, 208.9359, 298.01, -42.83026, 211.2797, 298.01, -39.25781, 214.7435, 298.01, -34.57031, 218.4974, 298.01, -32.22656, 219.9595, 298.01, -28.02053, 222.9984, 298.01, -27.53906, 223.4238, 298.01, -25.19531, 224.4187, 298.01, -22.85156, 225.8252, 298.01, -20.50781, 226.9067, 298.01, -18.16406, 228.4286, 298.01, -15.82031, 229.1235, 298.01, -14.9447, 230.0297, 298.01, -15.82031, 231.3969, 298.01, -16.94484, 232.3734, 298.01 };
-    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
+    size_t n = sizeof(groundTruthRaw) / sizeof(groundTruthRaw[0]); 
     std::vector<double> groundTruth(groundTruthRaw, groundTruthRaw+n);
     EXPECT_EQ(358u * 3, groundTruth.size());
     CheckGroundTruth(structures, 5, 8, groundTruth);
   }
 }
 
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 #if 0
 
 TEST(StructureSet, ReadFromJsonAndCompute1)
@@ -4458,6 +4464,8 @@
 }
 #endif
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 static bool CutStructureWithPlane(
   std::vector< std::pair<Point2D, Point2D> >& segments,
   const DicomStructure2& structure,
@@ -4479,12 +4487,17 @@
   return ok;
 }
 
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 static double pointsCoord1[] = { 2, 2, 3,  3,  6,  8, 8, 7, 8, 8, 6 };
 static double pointsCoord2[] = { 2, 6, 8, 10, 12, 10, 8, 6, 4, 2, 4 };
 static const size_t pointsCoord1Count = STONE_ARRAY_SIZE(pointsCoord1);
 static const size_t pointsCoord2Count = STONE_ARRAY_SIZE(pointsCoord2);
 const size_t POLYGON_POINT_COUNT = pointsCoord1Count;
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 static void CreateBasicStructure(DicomStructure2& structure)
 {
   // see https://www.dropbox.com/s/1o1vg53hsbvx4cc/test-rtstruct-polygons.jpg?dl=0
@@ -4691,6 +4704,10 @@
   EXPECT_EQ(8, numberOfVeryShortSegments);
 }
 
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
 TEST(DisjointDataSet, BasicTest)
 {
   const size_t ITEM_COUNT = 10;
@@ -4751,6 +4768,7 @@
   }
 }
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
 
 TEST(StructureSet, CutSagittalInsideClose)
 {
@@ -4770,6 +4788,10 @@
   EXPECT_TRUE(ok);
 }
 
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
+
 static size_t ConvertListOfSlabsToSegments_Add(RtStructRectanglesInSlab& rectangles, int row, double xmin, double xmax)
 {
   double ymin = static_cast<double>(row) * 5.0;
@@ -5355,6 +5377,8 @@
   ASSERT_NEAR(segments[i].second.y, 30.000000000000000, DELTA_MAX);
 }
 
+#ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
+
 TEST(StructureSet, ReadFromJsonPart2)
 {
   DicomStructureSet2 structureSet;
@@ -5373,5 +5397,7 @@
 }
 
 
+#endif 
+// BGO_ENABLE_DICOMSTRUCTURESETLOADER2