diff Framework/Layers/DicomStructureSetRendererFactory.cpp @ 123:ed0003f6102c wasm

dynamic loading of rt-struct renderers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 07 Oct 2017 13:11:12 +0200
parents e3433dabfb8d
children 44fc253d4876
line wrap: on
line diff
--- a/Framework/Layers/DicomStructureSetRendererFactory.cpp	Fri Oct 06 17:25:08 2017 +0200
+++ b/Framework/Layers/DicomStructureSetRendererFactory.cpp	Sat Oct 07 13:11:12 2017 +0200
@@ -21,6 +21,8 @@
 
 #include "DicomStructureSetRendererFactory.h"
 
+#include "../Toolbox/MessagingToolbox.h"
+
 #include <Core/OrthancException.h>
 
 namespace OrthancStone
@@ -70,12 +72,140 @@
   };
 
 
+  class DicomStructureSetRendererFactory::Operation : public Orthanc::IDynamicObject
+  {
+  public:
+    enum Type
+    {
+      Type_LoadStructureSet,
+      Type_LookupSopInstanceUid,
+      Type_LoadReferencedSlice
+    };
+    
+  private:
+    Type         type_;
+    std::string  value_;
+
+  public:
+    Operation(Type type,
+              const std::string& value) :
+      type_(type),
+      value_(value)
+    {
+    }
+
+    Type GetType() const
+    {
+      return type_;
+    }
+
+    const std::string& GetIdentifier() const
+    {
+      return value_;
+    }
+  };
+
+
+  void DicomStructureSetRendererFactory::NotifyError(const std::string& uri,
+                                                     Orthanc::IDynamicObject* payload)
+  {
+    // TODO
+  }
+
+  
+  void DicomStructureSetRendererFactory::NotifySuccess(const std::string& uri,
+                                                       const void* answer,
+                                                       size_t answerSize,
+                                                       Orthanc::IDynamicObject* payload)
+  {
+    std::auto_ptr<Operation> op(dynamic_cast<Operation*>(payload));
+
+    switch (op->GetType())
+    {
+      case Operation::Type_LoadStructureSet:
+      {
+        OrthancPlugins::FullOrthancDataset dataset(answer, answerSize);
+        structureSet_.reset(new DicomStructureSet(dataset));
+
+        std::set<std::string> instances;
+        structureSet_->GetReferencedInstances(instances);
+
+        for (std::set<std::string>::const_iterator it = instances.begin();
+             it != instances.end(); ++it)
+        {
+          orthanc_.SchedulePostRequest(*this, "/tools/lookup", *it,
+                                       new Operation(Operation::Type_LookupSopInstanceUid, *it));
+        }
+        
+        break;
+      }
+        
+      case Operation::Type_LookupSopInstanceUid:
+      {
+        Json::Value lookup;
+        
+        if (MessagingToolbox::ParseJson(lookup, answer, answerSize))
+        {
+          if (lookup.type() != Json::arrayValue ||
+              lookup.size() != 1 ||
+              !lookup[0].isMember("Type") ||
+              !lookup[0].isMember("Path") ||
+              lookup[0]["Type"].type() != Json::stringValue ||
+              lookup[0]["ID"].type() != Json::stringValue ||
+              lookup[0]["Type"].asString() != "Instance")
+          {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);          
+          }
+
+          const std::string& instance = lookup[0]["ID"].asString();
+          orthanc_.ScheduleGetRequest(*this, "/instances/" + instance + "/tags",
+                                      new Operation(Operation::Type_LoadReferencedSlice, instance));
+        }
+        else
+        {
+          // TODO
+        }
+        
+        break;
+      }
+
+      case Operation::Type_LoadReferencedSlice:
+      {
+        OrthancPlugins::FullOrthancDataset dataset(answer, answerSize);
+
+        Orthanc::DicomMap slice;
+        MessagingToolbox::ConvertDataset(slice, dataset);
+        structureSet_->AddReferencedSlice(slice);
+
+        LayerSourceBase::NotifyContentChange();
+
+        break;
+      }
+      
+      default:
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
+  } 
+
+  
+  DicomStructureSetRendererFactory::DicomStructureSetRendererFactory(IWebService& orthanc,
+                                                                     const std::string& instance) :
+    orthanc_(orthanc)
+  {
+    const std::string uri = "/instances/" + instance + "/tags?ignore-length=3006-0050";
+    orthanc_.ScheduleGetRequest(*this, uri, new Operation(Operation::Type_LoadStructureSet, instance));
+  }
+  
+  
   void DicomStructureSetRendererFactory::ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice)
   {
     bool isOpposite;
-    if (GeometryToolbox::IsParallelOrOpposite(isOpposite, viewportSlice.GetNormal(), structureSet_.GetNormal()))
+    if (structureSet_.get() != NULL &&
+        GeometryToolbox::IsParallelOrOpposite(isOpposite,
+                                              viewportSlice.GetNormal(),
+                                              structureSet_->GetNormal()))
     {
-      NotifyLayerReady(new Renderer(structureSet_, viewportSlice), viewportSlice, false);
+      NotifyLayerReady(new Renderer(*structureSet_, viewportSlice), viewportSlice, false);
     }
   }
 }