# HG changeset patch # User Sebastien Jodogne # Date 1507374672 -7200 # Node ID ed0003f6102c945a38f812d00fea201bb6f30401 # Parent e3433dabfb8dc4bd8dcb0bce7b8840104b1ac5f4 dynamic loading of rt-struct renderers diff -r e3433dabfb8d -r ed0003f6102c Applications/Samples/SingleVolumeApplication.h --- a/Applications/Samples/SingleVolumeApplication.h Fri Oct 06 17:25:08 2017 +0200 +++ b/Applications/Samples/SingleVolumeApplication.h Sat Oct 07 13:11:12 2017 +0200 @@ -88,9 +88,6 @@ }; - std::auto_ptr struct_; - - public: virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) { @@ -202,14 +199,6 @@ widget->SetLayerStyle(0, s); } #else - { - const std::string s = "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"; // IBA - //const std::string s = "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"; // 0522c0001 TCIA - - OrthancPlugins::OrthancHttpConnection orthanc; - struct_.reset(DicomStructureSet::SynchronousLoad(orthanc, s)); - } - std::auto_ptr ct(new OrthancVolumeImage(context.GetWebService(), false)); //ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d"); ct->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // IBA @@ -222,9 +211,12 @@ //pet->ScheduleLoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb"); // IBA 3 //pet->ScheduleLoadInstance("269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c"); // 0522c0001 TCIA + const std::string s = "54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"; // IBA + //const std::string s = "17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"; // 0522c0001 TCIA + widget->AddLayer(new VolumeImageSource(*ct)); widget->AddLayer(new VolumeImageSource(*pet)); - widget->AddLayer(new DicomStructureSetRendererFactory(*struct_)); + widget->AddLayer(new DicomStructureSetRendererFactory(context.GetWebService(), s)); context.AddInteractor(new Interactor(*pet, *widget, projection, 1)); //context.AddInteractor(new VolumeImageInteractor(*ct, *widget, projection)); diff -r e3433dabfb8d -r ed0003f6102c Framework/Layers/DicomStructureSetRendererFactory.cpp --- 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 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 op(dynamic_cast(payload)); + + switch (op->GetType()) + { + case Operation::Type_LoadStructureSet: + { + OrthancPlugins::FullOrthancDataset dataset(answer, answerSize); + structureSet_.reset(new DicomStructureSet(dataset)); + + std::set instances; + structureSet_->GetReferencedInstances(instances); + + for (std::set::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); } } } diff -r e3433dabfb8d -r ed0003f6102c Framework/Layers/DicomStructureSetRendererFactory.h --- a/Framework/Layers/DicomStructureSetRendererFactory.h Fri Oct 06 17:25:08 2017 +0200 +++ b/Framework/Layers/DicomStructureSetRendererFactory.h Sat Oct 07 13:11:12 2017 +0200 @@ -22,22 +22,33 @@ #pragma once #include "../Toolbox/DicomStructureSet.h" +#include "../Toolbox/IWebService.h" #include "LayerSourceBase.h" namespace OrthancStone { - class DicomStructureSetRendererFactory : public LayerSourceBase + class DicomStructureSetRendererFactory : + public LayerSourceBase, + private IWebService::ICallback { private: class Renderer; + class Operation; - DicomStructureSet& structureSet_; + virtual void NotifyError(const std::string& uri, + Orthanc::IDynamicObject* payload); + + virtual void NotifySuccess(const std::string& uri, + const void* answer, + size_t answerSize, + Orthanc::IDynamicObject* payload); + + IWebService& orthanc_; + std::auto_ptr structureSet_; public: - DicomStructureSetRendererFactory(DicomStructureSet& structureSet) : - structureSet_(structureSet) - { - } + DicomStructureSetRendererFactory(IWebService& orthanc, + const std::string& instance); virtual bool GetExtent(std::vector& points, const CoordinateSystem3D& viewportSlice) diff -r e3433dabfb8d -r ed0003f6102c Platforms/Generic/WebServiceGetCommand.cpp --- a/Platforms/Generic/WebServiceGetCommand.cpp Fri Oct 06 17:25:08 2017 +0200 +++ b/Platforms/Generic/WebServiceGetCommand.cpp Sat Oct 07 13:11:12 2017 +0200 @@ -40,6 +40,7 @@ void WebServiceGetCommand::Execute() { Orthanc::HttpClient client(parameters_, uri_); + client.SetTimeout(60); client.SetMethod(Orthanc::HttpMethod_Get); success_ = client.Apply(answer_); } diff -r e3433dabfb8d -r ed0003f6102c Platforms/Generic/WebServicePostCommand.cpp --- a/Platforms/Generic/WebServicePostCommand.cpp Fri Oct 06 17:25:08 2017 +0200 +++ b/Platforms/Generic/WebServicePostCommand.cpp Sat Oct 07 13:11:12 2017 +0200 @@ -41,6 +41,7 @@ void WebServicePostCommand::Execute() { Orthanc::HttpClient client(parameters_, uri_); + client.SetTimeout(60); client.SetMethod(Orthanc::HttpMethod_Post); client.GetBody().swap(body_); success_ = client.Apply(answer_);