Mercurial > hg > orthanc-stone
changeset 728:8190213e2279 am-dev
Merged default into am-dev
author | Alain Mazy <am@osimis.io> |
---|---|
date | Tue, 21 May 2019 13:25:58 +0200 |
parents | f185cfcb72a0 (current diff) 853e30d17cae (diff) |
children | 529189f399ec fe938bddb932 |
files | Applications/Samples/SimpleViewer/Messages.h Samples/Common/AngleMeasureTool.cpp Samples/Common/AngleMeasureTool.h Samples/Common/CreateAngleMeasureTracker.cpp Samples/Common/CreateAngleMeasureTracker.h Samples/Common/CreateCircleMeasureTracker.cpp Samples/Common/CreateCircleMeasureTracker.h Samples/Common/CreateLineMeasureTracker.cpp Samples/Common/CreateLineMeasureTracker.h Samples/Common/CreateMeasureTracker.cpp Samples/Common/CreateMeasureTracker.h Samples/Common/CreateSimpleTrackerAdapter.cpp Samples/Common/EditAngleMeasureTracker.cpp Samples/Common/EditAngleMeasureTracker.h Samples/Common/EditCircleMeasureTracker.cpp Samples/Common/EditCircleMeasureTracker.h Samples/Common/EditLineMeasureTracker.cpp Samples/Common/EditLineMeasureTracker.h Samples/Common/IFlexiblePointerTracker.h Samples/Common/LineMeasureTool.cpp Samples/Common/LineMeasureTool.h Samples/Common/MeasureCommands.cpp Samples/Common/MeasureCommands.h Samples/Common/MeasureTools.cpp Samples/Common/MeasureTools.h Samples/Common/MeasureToolsToolbox.cpp Samples/Common/MeasureToolsToolbox.h Samples/Common/MeasureTrackers.cpp Samples/Common/MeasureTrackers.h |
diffstat | 252 files changed, 7193 insertions(+), 4673 deletions(-) [+] |
line wrap: on
line diff
--- a/Applications/Generic/NativeStoneApplicationContext.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Generic/NativeStoneApplicationContext.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ namespace OrthancStone { - IWidget& NativeStoneApplicationContext::GlobalMutexLocker::SetCentralWidget(IWidget* widget) + Deprecated::IWidget& NativeStoneApplicationContext::GlobalMutexLocker::SetCentralWidget(Deprecated::IWidget* widget) { that_.centralViewport_.SetCentralWidget(widget); return *widget;
--- a/Applications/Generic/NativeStoneApplicationContext.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Generic/NativeStoneApplicationContext.h Tue May 21 13:25:58 2019 +0200 @@ -37,7 +37,7 @@ static void UpdateThread(NativeStoneApplicationContext* that); boost::recursive_mutex globalMutex_; - WidgetViewport centralViewport_; + Deprecated::WidgetViewport centralViewport_; boost::thread updateThread_; bool stopped_; unsigned int updateDelayInMs_; @@ -56,9 +56,9 @@ { } - IWidget& SetCentralWidget(IWidget* widget); // Takes ownership + Deprecated::IWidget& SetCentralWidget(Deprecated::IWidget* widget); // Takes ownership - IViewport& GetCentralViewport() + Deprecated::IViewport& GetCentralViewport() { return that_.centralViewport_; }
--- a/Applications/Generic/NativeStoneApplicationRunner.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Generic/NativeStoneApplicationRunner.cpp Tue May 21 13:25:58 2019 +0200 @@ -43,7 +43,7 @@ // Anonymous namespace to avoid clashes against other compilation modules namespace { - class LogStatusBar : public IStatusBar + class LogStatusBar : public Deprecated::IStatusBar { public: virtual void ClearMessage() @@ -202,17 +202,17 @@ { // use multiple threads to execute asynchronous tasks like // download content - Oracle oracle(6); + Deprecated::Oracle oracle(6); oracle.Start(); { - OracleWebService webService( + Deprecated::OracleWebService webService( broker_, oracle, webServiceParameters, context); context.SetWebService(webService); context.SetOrthancBaseUrl(webServiceParameters.GetUrl()); - OracleDelayedCallExecutor delayedExecutor(broker_, oracle, context); + Deprecated::OracleDelayedCallExecutor delayedExecutor(broker_, oracle, context); context.SetDelayedCallExecutor(delayedExecutor); application_.Initialize(&context, statusBar, parameters);
--- a/Applications/IStoneApplication.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/IStoneApplication.h Tue May 21 13:25:58 2019 +0200 @@ -47,7 +47,7 @@ virtual void DeclareStartupOptions(boost::program_options::options_description& options) = 0; virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) = 0; /** @@ -63,7 +63,7 @@ #endif virtual std::string GetTitle() const = 0; - virtual IWidget* GetCentralWidget() = 0; + virtual Deprecated::IWidget* GetCentralWidget() = 0; virtual void Finalize() = 0; }; }
--- a/Applications/Samples/CMakeLists.txt Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/CMakeLists.txt Tue May 21 13:25:58 2019 +0200 @@ -228,6 +228,7 @@ ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestCommands.cpp ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestExceptions.cpp ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestMessageBroker.cpp + ${ORTHANC_STONE_ROOT}/UnitTestsSources/TestStrategy.cpp ${ORTHANC_STONE_ROOT}/UnitTestsSources/UnitTestsMain.cpp )
--- a/Applications/Samples/SampleApplicationBase.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SampleApplicationBase.h Tue May 21 13:25:58 2019 +0200 @@ -42,11 +42,11 @@ { protected: // ownership is transferred to the application context - WorldSceneWidget* mainWidget_; + Deprecated::WorldSceneWidget* mainWidget_; public: virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) ORTHANC_OVERRIDE { } @@ -64,7 +64,7 @@ virtual void Finalize() ORTHANC_OVERRIDE {} - virtual IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainWidget_;} + virtual Deprecated::IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainWidget_;} #if ORTHANC_ENABLE_WASM==1 // default implementations for a single canvas named "canvas" in the HTML and an emtpy WasmApplicationAdapter
--- a/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/MainWidgetInteractor.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,27 +24,27 @@ namespace SimpleViewer { - IWorldSceneMouseTracker* MainWidgetInteractor::CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::IWorldSceneMouseTracker* MainWidgetInteractor::CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, MouseButton button, KeyboardModifiers modifiers, int viewportX, int viewportY, double x, double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { if (button == MouseButton_Left) { if (application_.GetCurrentTool() == Tool_LineMeasure) { - return new LineMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), + return new Deprecated::LineMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } else if (application_.GetCurrentTool() == Tool_CircleMeasure) { - return new CircleMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), + return new Deprecated::CircleMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } else if (application_.GetCurrentTool() == Tool_Crop) @@ -68,15 +68,15 @@ } void MainWidgetInteractor::MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { if (statusBar != NULL) { - Vector p = dynamic_cast<SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); + Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); char buf[64]; sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", @@ -85,18 +85,18 @@ } } - void MainWidgetInteractor::MouseWheel(WorldSceneWidget& widget, + void MainWidgetInteractor::MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } - void MainWidgetInteractor::KeyPressed(WorldSceneWidget& widget, + void MainWidgetInteractor::KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { switch (keyChar) {
--- a/Applications/Samples/SimpleViewer/MainWidgetInteractor.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/MainWidgetInteractor.h Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ class SimpleViewerApplication; - class MainWidgetInteractor : public IWorldSceneInteractor + class MainWidgetInteractor : public Deprecated::IWorldSceneInteractor { private: SimpleViewerApplication& application_; @@ -42,34 +42,34 @@ /** WorldSceneWidget: */ - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches); + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches); virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar); + Deprecated::IStatusBar* statusBar); - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar); + Deprecated::IStatusBar* statusBar); - virtual void KeyPressed(WorldSceneWidget& widget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar); + Deprecated::IStatusBar* statusBar); };
--- a/Applications/Samples/SimpleViewer/Messages.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#pragma once - -namespace SimpleViewer -{ - enum SimpleViewerMessageType - { - SimpleViewerMessageType_First = OrthancStone::MessageType_CustomMessage, - SimpleViewerMessageType_AppStatusUpdated - }; -}
--- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Tue May 21 13:25:58 2019 +0200 @@ -33,28 +33,26 @@ { void SimpleViewerApplication::Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) { - using namespace OrthancStone; - context_ = context; statusBar_ = &statusBar; {// initialize viewports and layout - mainLayout_ = new LayoutWidget("main-layout"); + mainLayout_ = new Deprecated::LayoutWidget("main-layout"); mainLayout_->SetPadding(10); mainLayout_->SetBackgroundCleared(true); mainLayout_->SetBackgroundColor(0, 0, 0); mainLayout_->SetHorizontal(); - thumbnailsLayout_ = new LayoutWidget("thumbnail-layout"); + thumbnailsLayout_ = new Deprecated::LayoutWidget("thumbnail-layout"); thumbnailsLayout_->SetPadding(10); thumbnailsLayout_->SetBackgroundCleared(true); thumbnailsLayout_->SetBackgroundColor(50, 50, 50); thumbnailsLayout_->SetVertical(); - mainWidget_ = new SliceViewerWidget(IObserver::GetBroker(), "main-viewport"); + mainWidget_ = new Deprecated::SliceViewerWidget(IObserver::GetBroker(), "main-viewport"); //mainWidget_->RegisterObserver(*this); // hierarchy @@ -62,7 +60,7 @@ mainLayout_->AddWidget(mainWidget_); // sources - smartLoader_.reset(new SmartLoader(IObserver::GetBroker(), context->GetOrthancApiClient())); + smartLoader_.reset(new Deprecated::SmartLoader(IObserver::GetBroker(), context->GetOrthancApiClient())); smartLoader_->SetImageQuality(SliceImageQuality_FullPam); mainLayout_->SetTransmitMouseOver(true); @@ -78,7 +76,7 @@ if (parameters.count("studyId") < 1) { LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - context->GetOrthancApiClient().GetJsonAsync("/studies", new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyListReceived)); + context->GetOrthancApiClient().GetJsonAsync("/studies", new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyListReceived)); } else { @@ -98,7 +96,7 @@ options.add(generic); } - void SimpleViewerApplication::OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void SimpleViewerApplication::OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -108,7 +106,7 @@ SelectStudy(response[0].asString()); } } - void SimpleViewerApplication::OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void SimpleViewerApplication::OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -116,12 +114,12 @@ { for (size_t i=0; i < response["Series"].size(); i++) { - context_->GetOrthancApiClient().GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnSeriesReceived)); + context_->GetOrthancApiClient().GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnSeriesReceived)); } } } - void SimpleViewerApplication::OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void SimpleViewerApplication::OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -154,13 +152,13 @@ { LOG(INFO) << "Loading thumbnail for series " << seriesId; - SliceViewerWidget* thumbnailWidget = - new SliceViewerWidget(IObserver::GetBroker(), "thumbnail-series-" + seriesId); + Deprecated::SliceViewerWidget* thumbnailWidget = + new Deprecated::SliceViewerWidget(IObserver::GetBroker(), "thumbnail-series-" + seriesId); thumbnails_.push_back(thumbnailWidget); thumbnailsLayout_->AddWidget(thumbnailWidget); thumbnailWidget->RegisterObserverCallback( - new Callable<SimpleViewerApplication, SliceViewerWidget::GeometryChangedMessage> + new Callable<SimpleViewerApplication, Deprecated::SliceViewerWidget::GeometryChangedMessage> (*this, &SimpleViewerApplication::OnWidgetGeometryChanged)); smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); @@ -169,13 +167,13 @@ void SimpleViewerApplication::SelectStudy(const std::string& studyId) { - context_->GetOrthancApiClient().GetJsonAsync("/studies/" + studyId, new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyReceived)); + context_->GetOrthancApiClient().GetJsonAsync("/studies/" + studyId, new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyReceived)); } - void SimpleViewerApplication::OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message) + void SimpleViewerApplication::OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message) { // TODO: The "const_cast" could probably be replaced by "mainWidget_" - const_cast<SliceViewerWidget&>(message.GetOrigin()).FitContent(); + const_cast<Deprecated::SliceViewerWidget&>(message.GetOrigin()).FitContent(); } void SimpleViewerApplication::SelectSeriesInMainViewport(const std::string& seriesId)
--- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Tue May 21 13:25:58 2019 +0200 @@ -51,7 +51,6 @@ #include "ThumbnailInteractor.h" #include "MainWidgetInteractor.h" #include "AppStatus.h" -#include "Messages.h" using namespace OrthancStone; @@ -67,13 +66,14 @@ { public: - struct StatusUpdatedMessage : public BaseMessage<SimpleViewerMessageType_AppStatusUpdated> + struct StatusUpdatedMessage : public IMessage { + ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); + const AppStatus& status_; StatusUpdatedMessage(const AppStatus& status) - : BaseMessage(), - status_(status) + : status_(status) { } }; @@ -83,18 +83,18 @@ std::auto_ptr<MainWidgetInteractor> mainWidgetInteractor_; std::auto_ptr<ThumbnailInteractor> thumbnailInteractor_; - LayoutWidget* mainLayout_; - LayoutWidget* thumbnailsLayout_; - SliceViewerWidget* mainWidget_; - std::vector<SliceViewerWidget*> thumbnails_; + Deprecated::LayoutWidget* mainLayout_; + Deprecated::LayoutWidget* thumbnailsLayout_; + Deprecated::SliceViewerWidget* mainWidget_; + std::vector<Deprecated::SliceViewerWidget*> thumbnails_; std::map<std::string, std::vector<std::string> > instancesIdsPerSeriesId_; std::map<std::string, Json::Value> seriesTags_; unsigned int currentInstanceIndex_; - OrthancStone::WidgetViewport* wasmViewport1_; - OrthancStone::WidgetViewport* wasmViewport2_; + Deprecated::WidgetViewport* wasmViewport1_; + Deprecated::WidgetViewport* wasmViewport2_; - IStatusBar* statusBar_; - std::auto_ptr<SmartLoader> smartLoader_; + Deprecated::IStatusBar* statusBar_; + std::auto_ptr<Deprecated::SmartLoader> smartLoader_; Orthanc::Font font_; @@ -112,24 +112,24 @@ } virtual void Finalize() ORTHANC_OVERRIDE {} - virtual IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainLayout_;} + virtual Deprecated::IWidget* GetCentralWidget() ORTHANC_OVERRIDE {return mainLayout_;} virtual void DeclareStartupOptions(boost::program_options::options_description& options) ORTHANC_OVERRIDE; virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) ORTHANC_OVERRIDE; - void OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + void OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - void OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + void OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - void OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + void OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId); void SelectStudy(const std::string& studyId); - void OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message); + void OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message); void SelectSeriesInMainViewport(const std::string& seriesId);
--- a/Applications/Samples/SimpleViewer/ThumbnailInteractor.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/ThumbnailInteractor.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,16 +24,16 @@ namespace SimpleViewer { - IWorldSceneMouseTracker* ThumbnailInteractor::CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::IWorldSceneMouseTracker* ThumbnailInteractor::CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, MouseButton button, KeyboardModifiers modifiers, int viewportX, int viewportY, double x, double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { if (button == MouseButton_Left) {
--- a/Applications/Samples/SimpleViewer/ThumbnailInteractor.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewer/ThumbnailInteractor.h Tue May 21 13:25:58 2019 +0200 @@ -29,7 +29,7 @@ class SimpleViewerApplication; - class ThumbnailInteractor : public IWorldSceneInteractor + class ThumbnailInteractor : public Deprecated::IWorldSceneInteractor { private: SimpleViewerApplication& application_; @@ -39,36 +39,36 @@ { } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches); + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches); virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) {} - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) {} - virtual void KeyPressed(WorldSceneWidget& widget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) {} };
--- a/Applications/Samples/SimpleViewerApplicationSingleFile.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SimpleViewerApplicationSingleFile.h Tue May 21 13:25:58 2019 +0200 @@ -47,7 +47,7 @@ public IObserver { private: - class ThumbnailInteractor : public IWorldSceneInteractor + class ThumbnailInteractor : public Deprecated::IWorldSceneInteractor { private: SimpleViewerApplication& application_; @@ -58,16 +58,16 @@ { } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, MouseButton button, KeyboardModifiers modifiers, int viewportX, int viewportY, double x, double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { if (button == MouseButton_Left) { @@ -79,31 +79,31 @@ } virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } - virtual void KeyPressed(WorldSceneWidget& widget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } }; - class MainWidgetInteractor : public IWorldSceneInteractor + class MainWidgetInteractor : public Deprecated::IWorldSceneInteractor { private: SimpleViewerApplication& application_; @@ -114,27 +114,27 @@ { } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, MouseButton button, KeyboardModifiers modifiers, int viewportX, int viewportY, double x, double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { if (button == MouseButton_Left) { if (application_.currentTool_ == Tool_LineMeasure) { - return new LineMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), + return new Deprecated::LineMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } else if (application_.currentTool_ == Tool_CircleMeasure) { - return new CircleMeasureTracker(statusBar, dynamic_cast<SliceViewerWidget&>(widget).GetSlice(), + return new Deprecated::CircleMeasureTracker(statusBar, dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice(), x, y, 255, 0, 0, application_.GetFont()); } } @@ -142,15 +142,15 @@ } virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { if (statusBar != NULL) { - Vector p = dynamic_cast<SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); + Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); char buf[64]; sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", @@ -159,18 +159,18 @@ } } - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } - virtual void KeyPressed(WorldSceneWidget& widget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { switch (keyChar) { @@ -241,19 +241,19 @@ Tool currentTool_; std::auto_ptr<MainWidgetInteractor> mainWidgetInteractor_; std::auto_ptr<ThumbnailInteractor> thumbnailInteractor_; - LayoutWidget* mainLayout_; - LayoutWidget* thumbnailsLayout_; - std::vector<SliceViewerWidget*> thumbnails_; + Deprecated::LayoutWidget* mainLayout_; + Deprecated::LayoutWidget* thumbnailsLayout_; + std::vector<Deprecated::SliceViewerWidget*> thumbnails_; std::map<std::string, std::vector<std::string> > instancesIdsPerSeriesId_; std::map<std::string, Json::Value> seriesTags_; unsigned int currentInstanceIndex_; - OrthancStone::WidgetViewport* wasmViewport1_; - OrthancStone::WidgetViewport* wasmViewport2_; + Deprecated::WidgetViewport* wasmViewport1_; + Deprecated::WidgetViewport* wasmViewport2_; - IStatusBar* statusBar_; - std::auto_ptr<SmartLoader> smartLoader_; + Deprecated::IStatusBar* statusBar_; + std::auto_ptr<Deprecated::SmartLoader> smartLoader_; Orthanc::Font font_; @@ -282,7 +282,7 @@ } virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) { using namespace OrthancStone; @@ -291,19 +291,19 @@ statusBar_ = &statusBar; {// initialize viewports and layout - mainLayout_ = new LayoutWidget("main-layout"); + mainLayout_ = new Deprecated::LayoutWidget("main-layout"); mainLayout_->SetPadding(10); mainLayout_->SetBackgroundCleared(true); mainLayout_->SetBackgroundColor(0, 0, 0); mainLayout_->SetHorizontal(); - thumbnailsLayout_ = new LayoutWidget("thumbnail-layout"); + thumbnailsLayout_ = new Deprecated::LayoutWidget("thumbnail-layout"); thumbnailsLayout_->SetPadding(10); thumbnailsLayout_->SetBackgroundCleared(true); thumbnailsLayout_->SetBackgroundColor(50, 50, 50); thumbnailsLayout_->SetVertical(); - mainWidget_ = new SliceViewerWidget(GetBroker(), "main-viewport"); + mainWidget_ = new Deprecated::SliceViewerWidget(GetBroker(), "main-viewport"); //mainWidget_->RegisterObserver(*this); // hierarchy @@ -311,7 +311,7 @@ mainLayout_->AddWidget(mainWidget_); // sources - smartLoader_.reset(new SmartLoader(GetBroker(), context->GetOrthancApiClient())); + smartLoader_.reset(new Deprecated::SmartLoader(GetBroker(), context->GetOrthancApiClient())); smartLoader_->SetImageQuality(SliceImageQuality_FullPam); mainLayout_->SetTransmitMouseOver(true); @@ -329,7 +329,7 @@ LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; context->GetOrthancApiClient().GetJsonAsync( "/studies", - new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage> + new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> (*this, &SimpleViewerApplication::OnStudyListReceived)); } else @@ -338,7 +338,7 @@ } } - void OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void OnStudyListReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -349,7 +349,7 @@ } } - void OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void OnStudyReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -359,13 +359,13 @@ { context_->GetOrthancApiClient().GetJsonAsync( "/series/" + response["Series"][(int)i].asString(), - new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage> + new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> (*this, &SimpleViewerApplication::OnSeriesReceived)); } } } - void OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + void OnSeriesReceived(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { const Json::Value& response = message.GetJson(); @@ -387,7 +387,7 @@ LoadThumbnailForSeries(seriesId, instancesIdsPerSeriesId_[seriesId][0]); // if this is the first thumbnail loaded, load the first instance in the mainWidget - SliceViewerWidget& widget = *dynamic_cast<SliceViewerWidget*>(mainWidget_); + Deprecated::SliceViewerWidget& widget = *dynamic_cast<Deprecated::SliceViewerWidget*>(mainWidget_); if (widget.GetLayerCount() == 0) { smartLoader_->SetFrameInWidget(widget, 0, instancesIdsPerSeriesId_[seriesId][0], 0); @@ -398,10 +398,10 @@ void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId) { LOG(INFO) << "Loading thumbnail for series " << seriesId; - SliceViewerWidget* thumbnailWidget = new SliceViewerWidget(GetBroker(), "thumbnail-series-" + seriesId); + Deprecated::SliceViewerWidget* thumbnailWidget = new Deprecated::SliceViewerWidget(GetBroker(), "thumbnail-series-" + seriesId); thumbnails_.push_back(thumbnailWidget); thumbnailsLayout_->AddWidget(thumbnailWidget); - thumbnailWidget->RegisterObserverCallback(new Callable<SimpleViewerApplication, SliceViewerWidget::GeometryChangedMessage>(*this, &SimpleViewerApplication::OnWidgetGeometryChanged)); + thumbnailWidget->RegisterObserverCallback(new Callable<SimpleViewerApplication, Deprecated::SliceViewerWidget::GeometryChangedMessage>(*this, &SimpleViewerApplication::OnWidgetGeometryChanged)); smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); thumbnailWidget->SetInteractor(*thumbnailInteractor_); } @@ -410,19 +410,19 @@ { LOG(INFO) << "Selecting study: " << studyId; context_->GetOrthancApiClient().GetJsonAsync( - "/studies/" + studyId, new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage> + "/studies/" + studyId, new Callable<SimpleViewerApplication, Deprecated::OrthancApiClient::JsonResponseReadyMessage> (*this, &SimpleViewerApplication::OnStudyReceived)); } - void OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message) + void OnWidgetGeometryChanged(const Deprecated::SliceViewerWidget::GeometryChangedMessage& message) { // TODO: The "const_cast" could probably be replaced by "mainWidget" - const_cast<SliceViewerWidget&>(message.GetOrigin()).FitContent(); + const_cast<Deprecated::SliceViewerWidget&>(message.GetOrigin()).FitContent(); } void SelectSeriesInMainViewport(const std::string& seriesId) { - SliceViewerWidget& widget = *dynamic_cast<SliceViewerWidget*>(mainWidget_); + Deprecated::SliceViewerWidget& widget = *dynamic_cast<Deprecated::SliceViewerWidget*>(mainWidget_); smartLoader_->SetFrameInWidget(widget, 0, instancesIdsPerSeriesId_[seriesId][0], 0); }
--- a/Applications/Samples/SingleFrameApplication.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SingleFrameApplication.h Tue May 21 13:25:58 2019 +0200 @@ -41,7 +41,7 @@ public IObserver { private: - class Interactor : public IWorldSceneInteractor + class Interactor : public Deprecated::IWorldSceneInteractor { private: SingleFrameApplication& application_; @@ -52,30 +52,30 @@ { } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, - const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { return NULL; } virtual void MouseOver(CairoContext& context, - WorldSceneWidget& widget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& widget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { if (statusBar != NULL) { - Vector p = dynamic_cast<SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); + Vector p = dynamic_cast<Deprecated::SliceViewerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); char buf[64]; sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", @@ -84,10 +84,10 @@ } } - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); @@ -106,11 +106,11 @@ } } - virtual void KeyPressed(WorldSceneWidget& widget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& widget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { switch (keyChar) { @@ -149,9 +149,9 @@ } - SliceViewerWidget& GetMainWidget() + Deprecated::SliceViewerWidget& GetMainWidget() { - return *dynamic_cast<SliceViewerWidget*>(mainWidget_); + return *dynamic_cast<Deprecated::SliceViewerWidget*>(mainWidget_); } @@ -184,7 +184,7 @@ } - void OnMainWidgetGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message) + void OnMainWidgetGeometryReady(const Deprecated::IVolumeSlicer::GeometryReadyMessage& message) { // Once the geometry of the series is downloaded from Orthanc, // display its middle slice, and adapt the viewport to fit this @@ -198,7 +198,7 @@ } std::auto_ptr<Interactor> mainWidgetInteractor_; - const DicomSeriesVolumeSlicer* source_; + const Deprecated::DicomSeriesVolumeSlicer* source_; unsigned int slice_; public: @@ -225,7 +225,7 @@ } virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) { using namespace OrthancStone; @@ -243,15 +243,15 @@ std::string instance = parameters["instance"].as<std::string>(); int frame = parameters["frame"].as<unsigned int>(); - mainWidget_ = new SliceViewerWidget(GetBroker(), "main-widget"); + mainWidget_ = new Deprecated::SliceViewerWidget(GetBroker(), "main-widget"); - std::auto_ptr<DicomSeriesVolumeSlicer> layer(new DicomSeriesVolumeSlicer(GetBroker(), context->GetOrthancApiClient())); + std::auto_ptr<Deprecated::DicomSeriesVolumeSlicer> layer(new Deprecated::DicomSeriesVolumeSlicer(GetBroker(), context->GetOrthancApiClient())); source_ = layer.get(); layer->LoadFrame(instance, frame); - layer->RegisterObserverCallback(new Callable<SingleFrameApplication, IVolumeSlicer::GeometryReadyMessage>(*this, &SingleFrameApplication::OnMainWidgetGeometryReady)); + layer->RegisterObserverCallback(new Callable<SingleFrameApplication, Deprecated::IVolumeSlicer::GeometryReadyMessage>(*this, &SingleFrameApplication::OnMainWidgetGeometryReady)); GetMainWidget().AddLayer(layer.release()); - RenderStyle s; + Deprecated::RenderStyle s; if (parameters["smooth"].as<bool>()) {
--- a/Applications/Samples/SingleFrameEditorApplication.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Samples/SingleFrameEditorApplication.h Tue May 21 13:25:58 2019 +0200 @@ -52,7 +52,7 @@ namespace Samples { class RadiographyEditorInteractor : - public IWorldSceneInteractor, + public Deprecated::IWorldSceneInteractor, public IObserver { private: @@ -97,16 +97,16 @@ { maskLayer_ = maskLayer; } - virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& worldWidget, - const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, - int viewportX, - int viewportY, - double x, - double y, - IStatusBar* statusBar, - const std::vector<Touch>& displayTouches) + virtual Deprecated::IWorldSceneMouseTracker* CreateMouseTracker(Deprecated::WorldSceneWidget& worldWidget, + const Deprecated::ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + Deprecated::IStatusBar* statusBar, + const std::vector<Deprecated::Touch>& displayTouches) { RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); @@ -226,11 +226,11 @@ } virtual void MouseOver(CairoContext& context, - WorldSceneWidget& worldWidget, - const ViewportGeometry& view, + Deprecated::WorldSceneWidget& worldWidget, + const Deprecated::ViewportGeometry& view, double x, double y, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); @@ -270,18 +270,18 @@ } } - virtual void MouseWheel(WorldSceneWidget& widget, + virtual void MouseWheel(Deprecated::WorldSceneWidget& widget, MouseWheelDirection direction, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { } - virtual void KeyPressed(WorldSceneWidget& worldWidget, + virtual void KeyPressed(Deprecated::WorldSceneWidget& worldWidget, KeyboardKeys key, char keyChar, KeyboardModifiers modifiers, - IStatusBar* statusBar) + Deprecated::IStatusBar* statusBar) { RadiographyWidget& widget = dynamic_cast<RadiographyWidget&>(worldWidget); @@ -455,7 +455,7 @@ } virtual void Initialize(StoneApplicationContext* context, - IStatusBar& statusBar, + Deprecated::IStatusBar& statusBar, const boost::program_options::variables_map& parameters) { using namespace OrthancStone; @@ -485,7 +485,7 @@ } std::string instance = parameters["instance"].as<std::string>(); - int frame = parameters["frame"].as<unsigned int>(); + //int frame = parameters["frame"].as<unsigned int>(); fontRegistry_.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16);
--- a/Applications/Sdl/SdlCairoSurface.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Sdl/SdlCairoSurface.cpp Tue May 21 13:25:58 2019 +0200 @@ -74,7 +74,7 @@ } - void SdlCairoSurface::Render(IViewport& viewport) + void SdlCairoSurface::Render(Deprecated::IViewport& viewport) { if (cairoSurface_.get() == NULL) {
--- a/Applications/Sdl/SdlCairoSurface.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Sdl/SdlCairoSurface.h Tue May 21 13:25:58 2019 +0200 @@ -46,7 +46,7 @@ void SetSize(unsigned int width, unsigned int height); - void Render(IViewport& viewport); + void Render(Deprecated::IViewport& viewport); }; }
--- a/Applications/Sdl/SdlEngine.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Sdl/SdlEngine.cpp Tue May 21 13:25:58 2019 +0200 @@ -146,15 +146,15 @@ switch (event.button.button) { case SDL_BUTTON_LEFT: - locker.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers, std::vector<Touch>()); + locker.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); break; case SDL_BUTTON_RIGHT: - locker.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers, std::vector<Touch>()); + locker.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); break; case SDL_BUTTON_MIDDLE: - locker.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers, std::vector<Touch>()); + locker.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers, std::vector<Deprecated::Touch>()); break; default: @@ -163,7 +163,7 @@ } else if (event.type == SDL_MOUSEMOTION) { - locker.GetCentralViewport().MouseMove(event.button.x, event.button.y, std::vector<Touch>()); + locker.GetCentralViewport().MouseMove(event.button.x, event.button.y, std::vector<Deprecated::Touch>()); } else if (event.type == SDL_MOUSEBUTTONUP) {
--- a/Applications/Sdl/SdlEngine.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Sdl/SdlEngine.h Tue May 21 13:25:58 2019 +0200 @@ -49,7 +49,7 @@ NativeStoneApplicationContext& context, MessageBroker& broker); - void OnViewportChanged(const IViewport::ViewportChangedMessage& message) + void OnViewportChanged(const Deprecated::IViewport::ViewportChangedMessage& message) { viewportChanged_ = true; }
--- a/Applications/Sdl/SdlStoneApplicationRunner.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/Sdl/SdlStoneApplicationRunner.cpp Tue May 21 13:25:58 2019 +0200 @@ -110,7 +110,7 @@ NativeStoneApplicationContext::GlobalMutexLocker locker(context); locker.GetCentralViewport().RegisterObserverCallback( - new Callable<SdlEngine, IViewport::ViewportChangedMessage> + new Callable<SdlEngine, Deprecated::IViewport::ViewportChangedMessage> (sdl, &SdlEngine::OnViewportChanged)); //context.GetCentralViewport().Register(sdl); // (*)
--- a/Applications/StoneApplicationContext.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Applications/StoneApplicationContext.cpp Tue May 21 13:25:58 2019 +0200 @@ -32,11 +32,11 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } - orthanc_.reset(new OrthancApiClient(broker_, *webService_, orthancBaseUrl_)); + orthanc_.reset(new Deprecated::OrthancApiClient(broker_, *webService_, orthancBaseUrl_)); } - IWebService& StoneApplicationContext::GetWebService() + Deprecated::IWebService& StoneApplicationContext::GetWebService() { if (webService_ == NULL) { @@ -47,7 +47,7 @@ } - OrthancApiClient& StoneApplicationContext::GetOrthancApiClient() + Deprecated::OrthancApiClient& StoneApplicationContext::GetOrthancApiClient() { if (orthanc_.get() == NULL) { @@ -58,7 +58,7 @@ } - void StoneApplicationContext::SetWebService(IWebService& webService) + void StoneApplicationContext::SetWebService(Deprecated::IWebService& webService) { webService_ = &webService; InitializeOrthanc();
--- a/Applications/StoneApplicationContext.h Thu May 16 19:10:38 2019 +0200 +++ b/Applications/StoneApplicationContext.h Tue May 21 13:25:58 2019 +0200 @@ -60,9 +60,9 @@ { private: MessageBroker& broker_; - IWebService* webService_; - IDelayedCallExecutor* delayedCallExecutor_; - std::auto_ptr<OrthancApiClient> orthanc_; + Deprecated::IWebService* webService_; + Deprecated::IDelayedCallExecutor* delayedCallExecutor_; + std::auto_ptr<Deprecated::OrthancApiClient> orthanc_; std::string orthancBaseUrl_; void InitializeOrthanc(); @@ -89,20 +89,20 @@ return webService_ != NULL; } - IWebService& GetWebService(); + Deprecated::IWebService& GetWebService(); - OrthancApiClient& GetOrthancApiClient(); + Deprecated::OrthancApiClient& GetOrthancApiClient(); - void SetWebService(IWebService& webService); + void SetWebService(Deprecated::IWebService& webService); void SetOrthancBaseUrl(const std::string& baseUrl); - void SetDelayedCallExecutor(IDelayedCallExecutor& delayedCallExecutor) + void SetDelayedCallExecutor(Deprecated::IDelayedCallExecutor& delayedCallExecutor) { delayedCallExecutor_ = &delayedCallExecutor; } - IDelayedCallExecutor& GetDelayedCallExecutor() + Deprecated::IDelayedCallExecutor& GetDelayedCallExecutor() { return *delayedCallExecutor_; }
--- a/Framework/Fonts/FontRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Fonts/FontRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -101,7 +101,9 @@ const FT_Byte* data = reinterpret_cast<const FT_Byte*>(fontContent_.c_str()); - CheckError(FT_New_Memory_Face(library_, data, fontContent_.size(), 0, &face_)); + CheckError(FT_New_Memory_Face( + library_, data, static_cast<FT_Long>(fontContent_.size()), 0, &face_)); + CheckError(FT_Set_Char_Size(face_, // handle to face object 0, // char_width in 1/64th of points fontSize * 64, // char_height in 1/64th of points
--- a/Framework/Fonts/GlyphTextureAlphabet.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Fonts/GlyphTextureAlphabet.cpp Tue May 21 13:25:58 2019 +0200 @@ -89,7 +89,7 @@ column_(0), row_(0) { - int c = boost::math::iround<int>(sqrt(static_cast<float>(countGlyphs))); + int c = boost::math::iround<float>(sqrt(static_cast<float>(countGlyphs))); if (c <= 0) { @@ -239,9 +239,9 @@ sourceAlphabet.GetAlphabet().Apply(size); TextureGenerator generator(alphabet_, - sourceAlphabet.GetAlphabet().GetSize(), - size.GetMaxWidth(), - size.GetMaxHeight()); + static_cast<unsigned int>(sourceAlphabet.GetAlphabet().GetSize()), + size.GetMaxWidth(), + size.GetMaxHeight()); sourceAlphabet.GetAlphabet().Apply(generator); texture_.reset(generator.ReleaseTexture());
--- a/Framework/Fonts/OpenGLTextCoordinates.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Fonts/OpenGLTextCoordinates.cpp Tue May 21 13:25:58 2019 +0200 @@ -35,8 +35,8 @@ const Orthanc::IDynamicObject* payload) { // Rendering coordinates - float rx1 = x - box_.GetLeft(); - float ry1 = y - box_.GetTop(); + float rx1 = static_cast<float>(x - box_.GetLeft()); + float ry1 = static_cast<float>(y - box_.GetTop()); float rx2 = rx1 + static_cast<float>(width); float ry2 = ry1 + static_cast<float>(height); @@ -81,8 +81,8 @@ OpenGLTextCoordinates::OpenGLTextCoordinates(const GlyphTextureAlphabet& alphabet, const std::string& utf8) : box_(alphabet.GetAlphabet(), utf8), - textureWidth_(alphabet.GetTextureWidth()), - textureHeight_(alphabet.GetTextureHeight()) + textureWidth_(static_cast<float>(alphabet.GetTextureWidth())), + textureHeight_(static_cast<float>(alphabet.GetTextureHeight())) { if (textureWidth_ <= 0 || textureHeight_ <= 0)
--- a/Framework/Layers/CircleMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/CircleMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,10 +24,10 @@ #include <stdio.h> #include <boost/math/constants/constants.hpp> -namespace OrthancStone +namespace Deprecated { CircleMeasureTracker::CircleMeasureTracker(IStatusBar* statusBar, - const CoordinateSystem3D& slice, + const OrthancStone::CoordinateSystem3D& slice, double x, double y, uint8_t red, @@ -48,14 +48,14 @@ } - void CircleMeasureTracker::Render(CairoContext& context, + void CircleMeasureTracker::Render(OrthancStone::CairoContext& context, double zoom) { double x = (x1_ + x2_) / 2.0; double y = (y1_ + y2_) / 2.0; - Vector tmp; - LinearAlgebra::AssignVector(tmp, x2_ - x1_, y2_ - y1_); + OrthancStone::Vector tmp; + OrthancStone::LinearAlgebra::AssignVector(tmp, x2_ - x1_, y2_ - y1_); double r = boost::numeric::ublas::norm_2(tmp) / 2.0; context.SetSourceColor(color_[0], color_[1], color_[2]); @@ -69,14 +69,14 @@ cairo_stroke(cr); cairo_restore(cr); - context.DrawText(font_, FormatRadius(), x, y, BitmapAnchor_Center); + context.DrawText(font_, FormatRadius(), x, y, OrthancStone::BitmapAnchor_Center); } double CircleMeasureTracker::GetRadius() const // In millimeters { - Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); - Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); + OrthancStone::Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); + OrthancStone::Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); return boost::numeric::ublas::norm_2(b - a) / 2.0; }
--- a/Framework/Layers/CircleMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/CircleMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -28,13 +28,13 @@ #include <Core/Images/Font.h> -namespace OrthancStone +namespace Deprecated { class CircleMeasureTracker : public IWorldSceneMouseTracker { private: IStatusBar* statusBar_; - CoordinateSystem3D slice_; + OrthancStone::CoordinateSystem3D slice_; double x1_; double y1_; double x2_; @@ -44,7 +44,7 @@ public: CircleMeasureTracker(IStatusBar* statusBar, - const CoordinateSystem3D& slice, + const OrthancStone::CoordinateSystem3D& slice, double x, double y, uint8_t red, @@ -57,7 +57,7 @@ return true; } - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom); double GetRadius() const; // In millimeters
--- a/Framework/Layers/ColorFrameRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/ColorFrameRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,11 +25,12 @@ #include <Core/Images/Image.h> #include <Core/Images/ImageProcessing.h> -namespace OrthancStone +namespace Deprecated { - CairoSurface* ColorFrameRenderer::GenerateDisplay(const RenderStyle& style) + OrthancStone::CairoSurface* ColorFrameRenderer::GenerateDisplay(const RenderStyle& style) { - std::auto_ptr<CairoSurface> display(new CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); + std::auto_ptr<OrthancStone::CairoSurface> display + (new OrthancStone::CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); Orthanc::ImageAccessor target; display->GetWriteableAccessor(target); @@ -41,7 +42,7 @@ ColorFrameRenderer::ColorFrameRenderer(const Orthanc::ImageAccessor& frame, - const CoordinateSystem3D& framePlane, + const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) :
--- a/Framework/Layers/ColorFrameRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/ColorFrameRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "FrameRenderer.h" -namespace OrthancStone +namespace Deprecated { class ColorFrameRenderer : public FrameRenderer { @@ -31,11 +31,11 @@ std::auto_ptr<Orthanc::ImageAccessor> frame_; // In RGB24 protected: - virtual CairoSurface* GenerateDisplay(const RenderStyle& style); + virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style); public: ColorFrameRenderer(const Orthanc::ImageAccessor& frame, - const CoordinateSystem3D& framePlane, + const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality);
--- a/Framework/Layers/DicomSeriesVolumeSlicer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/DicomSeriesVolumeSlicer.cpp Tue May 21 13:25:58 2019 +0200 @@ -29,7 +29,7 @@ #include <boost/lexical_cast.hpp> -namespace OrthancStone +namespace Deprecated { void DicomSeriesVolumeSlicer::OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message) @@ -63,8 +63,8 @@ virtual ILayerRenderer* CreateRenderer() const { - bool isFull = (message_.GetEffectiveQuality() == SliceImageQuality_FullPng || - message_.GetEffectiveQuality() == SliceImageQuality_FullPam); + bool isFull = (message_.GetEffectiveQuality() == OrthancStone::SliceImageQuality_FullPng || + message_.GetEffectiveQuality() == OrthancStone::SliceImageQuality_FullPam); return FrameRenderer::CreateRenderer(message_.GetImage(), message_.GetSlice(), isFull); } @@ -87,26 +87,27 @@ } - DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer(MessageBroker& broker, OrthancApiClient& orthanc) : + DicomSeriesVolumeSlicer::DicomSeriesVolumeSlicer(OrthancStone::MessageBroker& broker, + OrthancApiClient& orthanc) : IVolumeSlicer(broker), IObserver(broker), loader_(broker, orthanc), - quality_(SliceImageQuality_FullPng) + quality_(OrthancStone::SliceImageQuality_FullPng) { loader_.RegisterObserverCallback( - new Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryReadyMessage> + new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryReadyMessage> (*this, &DicomSeriesVolumeSlicer::OnSliceGeometryReady)); loader_.RegisterObserverCallback( - new Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryErrorMessage> + new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceGeometryErrorMessage> (*this, &DicomSeriesVolumeSlicer::OnSliceGeometryError)); loader_.RegisterObserverCallback( - new Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageReadyMessage> + new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageReadyMessage> (*this, &DicomSeriesVolumeSlicer::OnSliceImageReady)); loader_.RegisterObserverCallback( - new Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageErrorMessage> + new OrthancStone::Callable<DicomSeriesVolumeSlicer, OrthancSlicesLoader::SliceImageErrorMessage> (*this, &DicomSeriesVolumeSlicer::OnSliceImageError)); } @@ -130,8 +131,8 @@ } - bool DicomSeriesVolumeSlicer::GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice) + bool DicomSeriesVolumeSlicer::GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice) { size_t index; @@ -148,7 +149,7 @@ } - void DicomSeriesVolumeSlicer::ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) + void DicomSeriesVolumeSlicer::ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) { size_t index;
--- a/Framework/Layers/DicomSeriesVolumeSlicer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/DicomSeriesVolumeSlicer.h Tue May 21 13:25:58 2019 +0200 @@ -26,31 +26,31 @@ #include "../Toolbox/OrthancSlicesLoader.h" #include "../Toolbox/OrthancApiClient.h" -namespace OrthancStone +namespace Deprecated { // this class is in charge of loading a Frame. // once it's been loaded (first the geometry and then the image), // messages are sent to observers so they can use it class DicomSeriesVolumeSlicer : public IVolumeSlicer, - public IObserver + public OrthancStone::IObserver //private OrthancSlicesLoader::ISliceLoaderObserver { public: // TODO: Add "frame" and "instanceId" - class FrameReadyMessage : public OriginMessage<DicomSeriesVolumeSlicer> + class FrameReadyMessage : public OrthancStone::OriginMessage<DicomSeriesVolumeSlicer> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); private: const Orthanc::ImageAccessor& frame_; - SliceImageQuality imageQuality_; + OrthancStone::SliceImageQuality imageQuality_; const Slice& slice_; public: FrameReadyMessage(DicomSeriesVolumeSlicer& origin, const Orthanc::ImageAccessor& frame, - SliceImageQuality imageQuality, + OrthancStone::SliceImageQuality imageQuality, const Slice& slice) : OriginMessage(origin), frame_(frame), @@ -64,7 +64,7 @@ return frame_; } - SliceImageQuality GetImageQuality() const + OrthancStone::SliceImageQuality GetImageQuality() const { return imageQuality_; } @@ -80,10 +80,11 @@ class RendererFactory; OrthancSlicesLoader loader_; - SliceImageQuality quality_; + OrthancStone::SliceImageQuality quality_; public: - DicomSeriesVolumeSlicer(MessageBroker& broker, OrthancApiClient& orthanc); + DicomSeriesVolumeSlicer(OrthancStone::MessageBroker& broker, + OrthancApiClient& orthanc); void LoadSeries(const std::string& seriesId); @@ -92,12 +93,12 @@ void LoadFrame(const std::string& instanceId, unsigned int frame); - void SetImageQuality(SliceImageQuality quality) + void SetImageQuality(OrthancStone::SliceImageQuality quality) { quality_ = quality; } - SliceImageQuality GetImageQuality() const + OrthancStone::SliceImageQuality GetImageQuality() const { return quality_; } @@ -112,10 +113,10 @@ return loader_.GetSlice(slice); } - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice); + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice); - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice); + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice); protected: void OnSliceGeometryReady(const OrthancSlicesLoader::SliceGeometryReadyMessage& message);
--- a/Framework/Layers/DicomStructureSetSlicer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/DicomStructureSetSlicer.cpp Tue May 21 13:25:58 2019 +0200 @@ -21,7 +21,7 @@ #include "DicomStructureSetSlicer.h" -namespace OrthancStone +namespace Deprecated { class DicomStructureSetSlicer::Renderer : public ILayerRenderer { @@ -34,11 +34,11 @@ uint8_t green_; uint8_t blue_; std::string name_; - std::vector< std::vector<DicomStructureSet::PolygonPoint> > polygons_; + std::vector< std::vector<OrthancStone::DicomStructureSet::PolygonPoint> > polygons_; public: - Structure(DicomStructureSet& structureSet, - const CoordinateSystem3D& plane, + Structure(OrthancStone::DicomStructureSet& structureSet, + const OrthancStone::CoordinateSystem3D& plane, size_t index) : name_(structureSet.GetStructureName(index)) { @@ -46,7 +46,7 @@ visible_ = structureSet.ProjectStructure(polygons_, index, plane); } - void Render(CairoContext& context) + void Render(OrthancStone::CairoContext& context) { if (visible_) { @@ -72,12 +72,12 @@ typedef std::list<Structure*> Structures; - CoordinateSystem3D plane_; + OrthancStone::CoordinateSystem3D plane_; Structures structures_; public: - Renderer(DicomStructureSet& structureSet, - const CoordinateSystem3D& plane) : + Renderer(OrthancStone::DicomStructureSet& structureSet, + const OrthancStone::CoordinateSystem3D& plane) : plane_(plane) { for (size_t k = 0; k < structureSet.GetStructureCount(); k++) @@ -95,7 +95,7 @@ } } - virtual bool RenderLayer(CairoContext& context, + virtual bool RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view) { cairo_set_line_width(context.GetObject(), 2.0f / view.GetZoom()); @@ -110,7 +110,7 @@ return true; } - virtual const CoordinateSystem3D& GetLayerPlane() + virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() { return plane_; } @@ -129,12 +129,12 @@ class DicomStructureSetSlicer::RendererFactory : public LayerReadyMessage::IRendererFactory { private: - DicomStructureSet& structureSet_; - const CoordinateSystem3D& plane_; + OrthancStone::DicomStructureSet& structureSet_; + const OrthancStone::CoordinateSystem3D& plane_; public: - RendererFactory(DicomStructureSet& structureSet, - const CoordinateSystem3D& plane) : + RendererFactory(OrthancStone::DicomStructureSet& structureSet, + const OrthancStone::CoordinateSystem3D& plane) : structureSet_(structureSet), plane_(plane) { @@ -147,19 +147,19 @@ }; - DicomStructureSetSlicer::DicomStructureSetSlicer(MessageBroker& broker, + DicomStructureSetSlicer::DicomStructureSetSlicer(OrthancStone::MessageBroker& broker, StructureSetLoader& loader) : IVolumeSlicer(broker), IObserver(broker), loader_(loader) { loader_.RegisterObserverCallback( - new Callable<DicomStructureSetSlicer, StructureSetLoader::ContentChangedMessage> + new OrthancStone::Callable<DicomStructureSetSlicer, StructureSetLoader::ContentChangedMessage> (*this, &DicomStructureSetSlicer::OnStructureSetLoaded)); } - void DicomStructureSetSlicer::ScheduleLayerCreation(const CoordinateSystem3D& viewportPlane) + void DicomStructureSetSlicer::ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportPlane) { if (loader_.HasStructureSet()) {
--- a/Framework/Layers/DicomStructureSetSlicer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/DicomStructureSetSlicer.h Tue May 21 13:25:58 2019 +0200 @@ -24,11 +24,11 @@ #include "IVolumeSlicer.h" #include "../Volumes/StructureSetLoader.h" -namespace OrthancStone +namespace Deprecated { class DicomStructureSetSlicer : public IVolumeSlicer, - public IObserver + public OrthancStone::IObserver { private: class Renderer; @@ -42,15 +42,15 @@ } public: - DicomStructureSetSlicer(MessageBroker& broker, + DicomStructureSetSlicer(OrthancStone::MessageBroker& broker, StructureSetLoader& loader); - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportPlane) + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportPlane) { return false; } - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportPlane); + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportPlane); }; }
--- a/Framework/Layers/FrameRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/FrameRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,9 +26,9 @@ #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { - FrameRenderer::FrameRenderer(const CoordinateSystem3D& framePlane, + FrameRenderer::FrameRenderer(const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) : @@ -40,7 +40,7 @@ } - bool FrameRenderer::RenderLayer(CairoContext& context, + bool FrameRenderer::RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view) { if (!style_.visible_) @@ -70,11 +70,11 @@ switch (style_.interpolation_) { - case ImageInterpolation_Nearest: + case OrthancStone::ImageInterpolation_Nearest: cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); break; - case ImageInterpolation_Bilinear: + case OrthancStone::ImageInterpolation_Bilinear: cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); break; @@ -118,7 +118,7 @@ ILayerRenderer* FrameRenderer::CreateRenderer(const Orthanc::ImageAccessor& frame, - const Slice& framePlane, + const Deprecated::Slice& framePlane, bool isFullQuality) { if (frame.GetFormat() == Orthanc::PixelFormat_RGB24)
--- a/Framework/Layers/FrameRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/FrameRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -25,31 +25,31 @@ #include "../Toolbox/Slice.h" -namespace OrthancStone +namespace Deprecated { class FrameRenderer : public ILayerRenderer { private: - CoordinateSystem3D framePlane_; + OrthancStone::CoordinateSystem3D framePlane_; double pixelSpacingX_; double pixelSpacingY_; RenderStyle style_; bool isFullQuality_; - std::auto_ptr<CairoSurface> display_; + std::auto_ptr<OrthancStone::CairoSurface> display_; protected: - virtual CairoSurface* GenerateDisplay(const RenderStyle& style) = 0; + virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style) = 0; public: - FrameRenderer(const CoordinateSystem3D& framePlane, + FrameRenderer(const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality); - virtual bool RenderLayer(CairoContext& context, + virtual bool RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view); - virtual const CoordinateSystem3D& GetLayerPlane() + virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() { return framePlane_; } @@ -63,7 +63,7 @@ // TODO: Avoid cloning the "frame" static ILayerRenderer* CreateRenderer(const Orthanc::ImageAccessor& frame, - const Slice& framePlane, + const Deprecated::Slice& framePlane, bool isFullQuality); }; }
--- a/Framework/Layers/GrayscaleFrameRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/GrayscaleFrameRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,13 +24,13 @@ #include <Core/Images/Image.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { - CairoSurface* GrayscaleFrameRenderer::GenerateDisplay(const RenderStyle& style) + OrthancStone::CairoSurface* GrayscaleFrameRenderer::GenerateDisplay(const RenderStyle& style) { assert(frame_->GetFormat() == Orthanc::PixelFormat_Float32); - std::auto_ptr<CairoSurface> result; + std::auto_ptr<OrthancStone::CairoSurface> result; float windowCenter, windowWidth; style.ComputeWindowing(windowCenter, windowWidth, @@ -41,7 +41,7 @@ //LOG(INFO) << "Window: " << x0 << " => " << x1; - result.reset(new CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); + result.reset(new OrthancStone::CairoSurface(frame_->GetWidth(), frame_->GetHeight(), false /* no alpha */)); const uint8_t* lut = NULL; if (style.applyLut_) @@ -114,8 +114,8 @@ GrayscaleFrameRenderer::GrayscaleFrameRenderer(const Orthanc::ImageAccessor& frame, - const DicomFrameConverter& converter, - const CoordinateSystem3D& framePlane, + const Deprecated::DicomFrameConverter& converter, + const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) :
--- a/Framework/Layers/GrayscaleFrameRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/GrayscaleFrameRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include "FrameRenderer.h" #include "../Toolbox/DicomFrameConverter.h" -namespace OrthancStone +namespace Deprecated { class GrayscaleFrameRenderer : public FrameRenderer { @@ -35,12 +35,12 @@ Orthanc::PhotometricInterpretation photometric_; protected: - virtual CairoSurface* GenerateDisplay(const RenderStyle& style); + virtual OrthancStone::CairoSurface* GenerateDisplay(const RenderStyle& style); public: GrayscaleFrameRenderer(const Orthanc::ImageAccessor& frame, - const DicomFrameConverter& converter, - const CoordinateSystem3D& framePlane, + const Deprecated::DicomFrameConverter& converter, + const OrthancStone::CoordinateSystem3D& framePlane, double pixelSpacingX, double pixelSpacingY, bool isFullQuality);
--- a/Framework/Layers/ILayerRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/ILayerRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include "../Toolbox/ViewportGeometry.h" #include "RenderStyle.h" -namespace OrthancStone +namespace Deprecated { class ILayerRenderer : public boost::noncopyable { @@ -35,12 +35,12 @@ { } - virtual bool RenderLayer(CairoContext& context, + virtual bool RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view) = 0; virtual void SetLayerStyle(const RenderStyle& style) = 0; - virtual const CoordinateSystem3D& GetLayerPlane() = 0; + virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() = 0; virtual bool IsFullQuality() = 0; };
--- a/Framework/Layers/IVolumeSlicer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/IVolumeSlicer.h Tue May 21 13:25:58 2019 +0200 @@ -28,38 +28,38 @@ #include "Core/Images/Image.h" #include <boost/shared_ptr.hpp> -namespace OrthancStone +namespace Deprecated { - class IVolumeSlicer : public IObservable + class IVolumeSlicer : public OrthancStone::IObservable { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, IVolumeSlicer); ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, IVolumeSlicer); ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, IVolumeSlicer); - class SliceContentChangedMessage : public OriginMessage<IVolumeSlicer> + class SliceContentChangedMessage : public OrthancStone::OriginMessage<IVolumeSlicer> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); private: - const Slice& slice_; + const Deprecated::Slice& slice_; public: SliceContentChangedMessage(IVolumeSlicer& origin, - const Slice& slice) : + const Deprecated::Slice& slice) : OriginMessage(origin), slice_(slice) { } - const Slice& GetSlice() const + const Deprecated::Slice& GetSlice() const { return slice_; } }; - class LayerReadyMessage : public OriginMessage<IVolumeSlicer> + class LayerReadyMessage : public OrthancStone::OriginMessage<IVolumeSlicer> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -76,12 +76,12 @@ private: const IRendererFactory& factory_; - const CoordinateSystem3D& slice_; + const OrthancStone::CoordinateSystem3D& slice_; public: LayerReadyMessage(IVolumeSlicer& origin, const IRendererFactory& rendererFactory, - const CoordinateSystem3D& slice) : + const OrthancStone::CoordinateSystem3D& slice) : OriginMessage(origin), factory_(rendererFactory), slice_(slice) @@ -93,36 +93,36 @@ return factory_.CreateRenderer(); } - const CoordinateSystem3D& GetSlice() const + const OrthancStone::CoordinateSystem3D& GetSlice() const { return slice_; } }; - class LayerErrorMessage : public OriginMessage<IVolumeSlicer> + class LayerErrorMessage : public OrthancStone::OriginMessage<IVolumeSlicer> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); private: - const CoordinateSystem3D& slice_; + const OrthancStone::CoordinateSystem3D& slice_; public: LayerErrorMessage(IVolumeSlicer& origin, - const CoordinateSystem3D& slice) : + const OrthancStone::CoordinateSystem3D& slice) : OriginMessage(origin), slice_(slice) { } - const CoordinateSystem3D& GetSlice() const + const OrthancStone::CoordinateSystem3D& GetSlice() const { return slice_; } }; - IVolumeSlicer(MessageBroker& broker) : + IVolumeSlicer(OrthancStone::MessageBroker& broker) : IObservable(broker) { } @@ -131,9 +131,9 @@ { } - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice) = 0; + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice) = 0; - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) = 0; + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) = 0; }; }
--- a/Framework/Layers/LineLayerRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/LineLayerRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -21,13 +21,13 @@ #include "LineLayerRenderer.h" -namespace OrthancStone +namespace Deprecated { LineLayerRenderer::LineLayerRenderer(double x1, double y1, double x2, double y2, - const CoordinateSystem3D& plane) : + const OrthancStone::CoordinateSystem3D& plane) : x1_(x1), y1_(y1), x2_(x2), @@ -39,7 +39,7 @@ } - bool LineLayerRenderer::RenderLayer(CairoContext& context, + bool LineLayerRenderer::RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view) { if (visible_)
--- a/Framework/Layers/LineLayerRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/LineLayerRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "ILayerRenderer.h" -namespace OrthancStone +namespace Deprecated { class LineLayerRenderer : public ILayerRenderer { @@ -32,7 +32,7 @@ double y1_; double x2_; double y2_; - CoordinateSystem3D plane_; + OrthancStone::CoordinateSystem3D plane_; bool visible_; uint8_t color_[3]; @@ -41,14 +41,14 @@ double y1, double x2, double y2, - const CoordinateSystem3D& plane); + const OrthancStone::CoordinateSystem3D& plane); - virtual bool RenderLayer(CairoContext& context, + virtual bool RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view); virtual void SetLayerStyle(const RenderStyle& style); - virtual const CoordinateSystem3D& GetLayerPlane() + virtual const OrthancStone::CoordinateSystem3D& GetLayerPlane() { return plane_; }
--- a/Framework/Layers/LineMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/LineMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,10 +23,10 @@ #include <stdio.h> -namespace OrthancStone +namespace Deprecated { LineMeasureTracker::LineMeasureTracker(IStatusBar* statusBar, - const CoordinateSystem3D& slice, + const OrthancStone::CoordinateSystem3D& slice, double x, double y, uint8_t red, @@ -47,7 +47,7 @@ } - void LineMeasureTracker::Render(CairoContext& context, + void LineMeasureTracker::Render(OrthancStone::CairoContext& context, double zoom) { context.SetSourceColor(color_[0], color_[1], color_[2]); @@ -60,19 +60,19 @@ if (y2_ - y1_ < 0) { - context.DrawText(font_, FormatLength(), x2_, y2_ - 5, BitmapAnchor_BottomCenter); + context.DrawText(font_, FormatLength(), x2_, y2_ - 5, OrthancStone::BitmapAnchor_BottomCenter); } else { - context.DrawText(font_, FormatLength(), x2_, y2_ + 5, BitmapAnchor_TopCenter); + context.DrawText(font_, FormatLength(), x2_, y2_ + 5, OrthancStone::BitmapAnchor_TopCenter); } } double LineMeasureTracker::GetLength() const // In millimeters { - Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); - Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); + OrthancStone::Vector a = slice_.MapSliceToWorldCoordinates(x1_, y1_); + OrthancStone::Vector b = slice_.MapSliceToWorldCoordinates(x2_, y2_); return boost::numeric::ublas::norm_2(b - a); }
--- a/Framework/Layers/LineMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/LineMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -26,13 +26,13 @@ #include "../Viewport/IStatusBar.h" #include "../Toolbox/CoordinateSystem3D.h" -namespace OrthancStone +namespace Deprecated { class LineMeasureTracker : public IWorldSceneMouseTracker { private: IStatusBar* statusBar_; - CoordinateSystem3D slice_; + OrthancStone::CoordinateSystem3D slice_; double x1_; double y1_; double x2_; @@ -43,7 +43,7 @@ public: LineMeasureTracker(IStatusBar* statusBar, - const CoordinateSystem3D& slice, + const OrthancStone::CoordinateSystem3D& slice, double x, double y, uint8_t red, @@ -56,7 +56,7 @@ return true; } - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom); double GetLength() const; // In millimeters
--- a/Framework/Layers/RenderStyle.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/RenderStyle.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,13 +23,13 @@ #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { RenderStyle::RenderStyle() { visible_ = true; reverse_ = false; - windowing_ = ImageWindowing_Custom; + windowing_ = OrthancStone::ImageWindowing_Custom; alpha_ = 1; applyLut_ = false; lut_ = Orthanc::EmbeddedResources::COLORMAP_HOT; @@ -39,7 +39,7 @@ drawColor_[2] = 255; customWindowCenter_ = 128; customWindowWidth_ = 256; - interpolation_ = ImageInterpolation_Nearest; + interpolation_ = OrthancStone::ImageInterpolation_Nearest; fontSize_ = 14; } @@ -49,7 +49,7 @@ float defaultCenter, float defaultWidth) const { - if (windowing_ == ImageWindowing_Custom) + if (windowing_ == OrthancStone::ImageWindowing_Custom) { targetCenter = customWindowCenter_; targetWidth = customWindowWidth_;
--- a/Framework/Layers/RenderStyle.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/RenderStyle.h Tue May 21 13:25:58 2019 +0200 @@ -27,13 +27,13 @@ #include <stdint.h> -namespace OrthancStone +namespace Deprecated { struct RenderStyle { bool visible_; bool reverse_; - ImageWindowing windowing_; + OrthancStone::ImageWindowing windowing_; float alpha_; // In [0,1] bool applyLut_; Orthanc::EmbeddedResources::FileResourceId lut_; @@ -41,7 +41,7 @@ uint8_t drawColor_[3]; float customWindowCenter_; float customWindowWidth_; - ImageInterpolation interpolation_; + OrthancStone::ImageInterpolation interpolation_; unsigned int fontSize_; RenderStyle();
--- a/Framework/Layers/SeriesFrameRendererFactory.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SeriesFrameRendererFactory.cpp Tue May 21 13:25:58 2019 +0200 @@ -30,7 +30,7 @@ #include <Plugins/Samples/Common/DicomDatasetReader.h> -namespace OrthancStone +namespace Deprecated { void SeriesFrameRendererFactory::ReadCurrentFrameDataset(size_t frame) {
--- a/Framework/Layers/SeriesFrameRendererFactory.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SeriesFrameRendererFactory.h Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include "../Toolbox/ISeriesLoader.h" -namespace OrthancStone +namespace Deprecated { class SeriesFrameRendererFactory : public ILayerRendererFactory {
--- a/Framework/Layers/SingleFrameRendererFactory.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SingleFrameRendererFactory.cpp Tue May 21 13:25:58 2019 +0200 @@ -29,7 +29,7 @@ #include <Plugins/Samples/Common/FullOrthancDataset.h> #include <Plugins/Samples/Common/DicomDatasetReader.h> -namespace OrthancStone +namespace Deprecated { SingleFrameRendererFactory::SingleFrameRendererFactory(OrthancPlugins::IOrthancConnection& orthanc, const std::string& instanceId,
--- a/Framework/Layers/SingleFrameRendererFactory.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SingleFrameRendererFactory.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include "ILayerRendererFactory.h" #include <Plugins/Samples/Common/IOrthancConnection.h> -namespace OrthancStone +namespace Deprecated { class SingleFrameRendererFactory : public ILayerRendererFactory {
--- a/Framework/Layers/SliceOutlineRenderer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SliceOutlineRenderer.cpp Tue May 21 13:25:58 2019 +0200 @@ -21,9 +21,9 @@ #include "SliceOutlineRenderer.h" -namespace OrthancStone +namespace Deprecated { - bool SliceOutlineRenderer::RenderLayer(CairoContext& context, + bool SliceOutlineRenderer::RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view) { if (style_.visible_)
--- a/Framework/Layers/SliceOutlineRenderer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Layers/SliceOutlineRenderer.h Tue May 21 13:25:58 2019 +0200 @@ -24,12 +24,12 @@ #include "ILayerRenderer.h" #include "../Toolbox/Slice.h" -namespace OrthancStone +namespace Deprecated { class SliceOutlineRenderer : public ILayerRenderer { private: - CoordinateSystem3D geometry_; + OrthancStone::CoordinateSystem3D geometry_; double pixelSpacingX_; double pixelSpacingY_; unsigned int width_; @@ -46,7 +46,7 @@ { } - virtual bool RenderLayer(CairoContext& context, + virtual bool RenderLayer(OrthancStone::CairoContext& context, const ViewportGeometry& view); virtual void SetLayerStyle(const RenderStyle& style) @@ -54,7 +54,7 @@ style_ = style; } - virtual const CoordinateSystem3D& GetLayerSlice() + virtual const OrthancStone::CoordinateSystem3D& GetLayerSlice() { return geometry_; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/BasicFetchingItemsSorter.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,74 @@ +/** + * 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 "BasicFetchingItemsSorter.h" + +#include <Core/OrthancException.h> + +namespace OrthancStone +{ + BasicFetchingItemsSorter::BasicFetchingItemsSorter(unsigned int itemsCount) : + itemsCount_(itemsCount) + { + if (itemsCount == 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + void BasicFetchingItemsSorter::Sort(std::vector<unsigned int>& target, + unsigned int current) + { + if (current >= itemsCount_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + target.clear(); + target.reserve(itemsCount_); + target.push_back(current); + + const unsigned int countBelow = current; + const unsigned int countAbove = (itemsCount_ - 1) - current; + const unsigned int n = std::min(countBelow, countAbove); + + for (unsigned int i = 1; i <= n; i++) + { + assert(current + i < itemsCount_ && + current >= i); + target.push_back(current + i); + target.push_back(current - i); + } + + for (unsigned int i = current - n; i > 0; i--) + { + target.push_back(i - 1); + } + + for (unsigned int i = current + n + 1; i < itemsCount_; i++) + { + target.push_back(i); + } + + assert(target.size() == itemsCount_); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/BasicFetchingItemsSorter.h Tue May 21 13:25:58 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/>. + **/ + + +#pragma once + +#include "IFetchingItemsSorter.h" + +namespace OrthancStone +{ + class BasicFetchingItemsSorter : public IFetchingItemsSorter + { + private: + unsigned int itemsCount_; + + public: + BasicFetchingItemsSorter(unsigned int itemsCount); + + virtual unsigned int GetItemsCount() const + { + return itemsCount_; + } + + virtual void Sort(std::vector<unsigned int>& target, + unsigned int current); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/BasicFetchingStrategy.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,145 @@ +/** + * 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 "BasicFetchingStrategy.h" + +#include <Core/OrthancException.h> + +namespace OrthancStone +{ + void BasicFetchingStrategy::Schedule(unsigned int item, + unsigned int quality) + { + assert(item < GetItemsCount() && + quality <= maxQuality_); + + if (nextQuality_[item] <= quality) + { + content_.push_back(ContentItem(item, quality)); + } + } + + + BasicFetchingStrategy::BasicFetchingStrategy(IFetchingItemsSorter* sorter, // Takes ownership + unsigned int maxQuality) : + sorter_(sorter), + maxQuality_(maxQuality), + position_(0), + blockSize_(2) + { + if (sorter == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + + nextQuality_.resize(sorter_->GetItemsCount(), 0); // Does not change along calls to "SetCurrent()" + + SetCurrent(0); + } + + + void BasicFetchingStrategy::SetBlockSize(unsigned int size) + { + if (size <= 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + blockSize_ = size; + } + + + bool BasicFetchingStrategy::GetNext(unsigned int& item, + unsigned int& quality) + { + if (position_ >= content_.size()) + { + return false; + } + else + { + item = content_[position_].GetItem(); + quality = content_[position_].GetQuality(); + + assert(nextQuality_[item] <= quality); + nextQuality_[item] = quality + 1; + + position_ ++; + return true; + } + } + + + void BasicFetchingStrategy::SetCurrent(unsigned int item) + { + // TODO - This function is O(N) complexity where "N" is the + // number of items times the max quality. Could use a LRU index. + + position_ = 0; + + std::vector<unsigned int> v; + sorter_->Sort(v, item); + + assert(v.size() == GetItemsCount()); + + if (v.size() == 0) + { + return; + } + + content_.clear(); + content_.reserve(v.size() * maxQuality_); + + Schedule(v.front(), maxQuality_); + + for (unsigned int q = 0; q <= maxQuality_; q++) + { + unsigned int start = 1 + q * blockSize_; + unsigned int end = start + blockSize_; + + if (q == maxQuality_ || + end > v.size()) + { + end = static_cast<int>(v.size()); + } + + unsigned int a = 0; + if (maxQuality_ >= q + 1) + { + a = maxQuality_ - q - 1; + } + + for (unsigned int j = a; j <= maxQuality_; j++) + { + for (unsigned int i = start; i < end; i++) + { + Schedule(v[i], j); + } + } + } + } + + + void BasicFetchingStrategy::RecycleFurthest(unsigned int& item) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/BasicFetchingStrategy.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,94 @@ +/** + * 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 "IFetchingItemsSorter.h" +#include "IFetchingStrategy.h" + +#include <memory> + +namespace OrthancStone +{ + class BasicFetchingStrategy : public IFetchingStrategy + { + private: + class ContentItem + { + private: + unsigned int item_; + unsigned int quality_; + + public: + ContentItem(unsigned int item, + unsigned int quality) : + item_(item), + quality_(quality) + { + } + + unsigned int GetItem() const + { + return item_; + } + + unsigned int GetQuality() const + { + return quality_; + } + }; + + std::auto_ptr<IFetchingItemsSorter> sorter_; + std::vector<unsigned int> nextQuality_; + unsigned int maxQuality_; + std::vector<ContentItem> content_; + size_t position_; + unsigned int blockSize_; + + void Schedule(unsigned int item, + unsigned int quality); + + public: + BasicFetchingStrategy(IFetchingItemsSorter* sorter, // Takes ownership + unsigned int maxQuality); + + virtual unsigned int GetItemsCount() const + { + return sorter_->GetItemsCount(); + } + + virtual unsigned int GetMaxQuality() const + { + return maxQuality_; + } + + // WARNING - This parameters is only considered during the next + // call to SetCurrent(). + void SetBlockSize(unsigned int size); + + virtual bool GetNext(unsigned int& item, + unsigned int& quality); + + virtual void SetCurrent(unsigned int item); + + virtual void RecycleFurthest(unsigned int& item); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/IFetchingItemsSorter.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,42 @@ +/** + * 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 <boost/noncopyable.hpp> +#include <vector> + +namespace OrthancStone +{ + class IFetchingItemsSorter : public boost::noncopyable + { + public: + virtual ~IFetchingItemsSorter() + { + } + + virtual unsigned int GetItemsCount() const = 0; + + // Sort a set of items given the current item + virtual void Sort(std::vector<unsigned int>& target, + unsigned int current) = 0; + }; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/IFetchingStrategy.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,49 @@ +/** + * 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 <boost/noncopyable.hpp> + +namespace OrthancStone +{ + class IFetchingStrategy : public boost::noncopyable + { + public: + virtual ~IFetchingStrategy() + { + } + + virtual unsigned int GetItemsCount() const = 0; + + virtual unsigned int GetMaxQuality() const = 0; + + virtual bool GetNext(unsigned int& item, + unsigned int& quality) = 0; + + virtual void SetCurrent(unsigned int item) = 0; + + // Ask the strategy to re-schedule the item with the lowest + // priority in the fetching order. This allows to know which item + // should be dropped from a cache. + virtual void RecycleFurthest(unsigned int& item) = 0; + }; +};
--- a/Framework/OpenGL/OpenGLShader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/OpenGL/OpenGLShader.cpp Tue May 21 13:25:58 2019 +0200 @@ -35,7 +35,7 @@ GLint sourceStringLengths[1]; sourceString[0] = source.c_str(); - sourceStringLengths[0] = source.length(); + sourceStringLengths[0] = static_cast<GLint>(source.length()); GLuint shader = glCreateShader(type); if (shader == 0)
--- a/Framework/Radiography/RadiographyDicomLayer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyDicomLayer.cpp Tue May 21 13:25:58 2019 +0200 @@ -54,7 +54,7 @@ void RadiographyDicomLayer::SetDicomTags(const OrthancPlugins::FullOrthancDataset& dataset) { - converter_.reset(new DicomFrameConverter); + converter_.reset(new Deprecated::DicomFrameConverter); converter_->ReadParameters(dataset); ApplyConverter(); @@ -112,7 +112,7 @@ } - void RadiographyDicomLayer::SetDicomFrameConverter(DicomFrameConverter* converter) + void RadiographyDicomLayer::SetDicomFrameConverter(Deprecated::DicomFrameConverter* converter) { converter_.reset(converter); }
--- a/Framework/Radiography/RadiographyDicomLayer.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyDicomLayer.h Tue May 21 13:25:58 2019 +0200 @@ -21,19 +21,20 @@ #pragma once +#include "../Toolbox/DicomFrameConverter.h" #include "RadiographyLayer.h" + #include <Plugins/Samples/Common/FullOrthancDataset.h> namespace OrthancStone { class RadiographyScene; - class DicomFrameConverter; class RadiographyDicomLayer : public RadiographyLayer { private: std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData - std::auto_ptr<DicomFrameConverter> converter_; + std::auto_ptr<Deprecated::DicomFrameConverter> converter_; std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 std::string instanceId_; unsigned int frame_; @@ -65,10 +66,10 @@ const Orthanc::ImageAccessor* GetSourceImage() const {return source_.get();} // currently need this access to serialize scene in plain old data to send to a WASM worker - const DicomFrameConverter& GetDicomFrameConverter() const {return *converter_;} // currently need this access to serialize scene in plain old data to send to a WASM worker + const Deprecated::DicomFrameConverter& GetDicomFrameConverter() const {return *converter_;} // currently need this access to serialize scene in plain old data to send to a WASM worker // Takes ownership - void SetDicomFrameConverter(DicomFrameConverter* converter); + void SetDicomFrameConverter(Deprecated::DicomFrameConverter* converter); virtual void Render(Orthanc::ImageAccessor& buffer, const AffineTransform2D& viewTransform,
--- a/Framework/Radiography/RadiographyLayerCropTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerCropTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -66,7 +66,7 @@ RadiographyLayerCropTracker::RadiographyLayerCropTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, const ControlPoint& startControlPoint) : undoRedoStack_(undoRedoStack), @@ -100,8 +100,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { if (accessor_.IsValid()) {
--- a/Framework/Radiography/RadiographyLayerCropTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerCropTracker.h Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ namespace OrthancStone { - class RadiographyLayerCropTracker : public IWorldSceneMouseTracker + class RadiographyLayerCropTracker : public Deprecated::IWorldSceneMouseTracker { private: class UndoRedoCommand; @@ -44,7 +44,7 @@ public: RadiographyLayerCropTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, const ControlPoint& startControlPoint); @@ -62,7 +62,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Radiography/RadiographyLayerMaskTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerMaskTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -85,7 +85,7 @@ RadiographyLayerMaskTracker::RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, const ControlPoint& startSceneControlPoint) : undoRedoStack_(undoRedoStack), @@ -116,8 +116,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { if (accessor_.IsValid()) {
--- a/Framework/Radiography/RadiographyLayerMaskTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerMaskTracker.h Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ namespace OrthancStone { - class RadiographyLayerMaskTracker : public IWorldSceneMouseTracker + class RadiographyLayerMaskTracker : public Deprecated::IWorldSceneMouseTracker { private: class UndoRedoCommand; @@ -41,7 +41,7 @@ public: RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, const ControlPoint& startSceneControlPoint); @@ -59,7 +59,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Radiography/RadiographyLayerMoveTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerMoveTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -98,8 +98,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { if (accessor_.IsValid()) {
--- a/Framework/Radiography/RadiographyLayerMoveTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerMoveTracker.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ namespace OrthancStone { - class RadiographyLayerMoveTracker : public IWorldSceneMouseTracker + class RadiographyLayerMoveTracker : public Deprecated::IWorldSceneMouseTracker { private: class UndoRedoCommand; @@ -62,7 +62,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Radiography/RadiographyLayerResizeTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerResizeTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -159,8 +159,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { static const double ROUND_SCALING = 0.1;
--- a/Framework/Radiography/RadiographyLayerResizeTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerResizeTracker.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ namespace OrthancStone { - class RadiographyLayerResizeTracker : public IWorldSceneMouseTracker + class RadiographyLayerResizeTracker : public Deprecated::IWorldSceneMouseTracker { private: class UndoRedoCommand; @@ -63,7 +63,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Radiography/RadiographyLayerRotateTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerRotateTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -88,7 +88,7 @@ RadiographyLayerRotateTracker::RadiographyLayerRotateTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, double x, double y, @@ -133,8 +133,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { static const double ROUND_ANGLE = 15.0 / 180.0 * boost::math::constants::pi<double>();
--- a/Framework/Radiography/RadiographyLayerRotateTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyLayerRotateTracker.h Tue May 21 13:25:58 2019 +0200 @@ -29,7 +29,7 @@ namespace OrthancStone { - class RadiographyLayerRotateTracker : public IWorldSceneMouseTracker + class RadiographyLayerRotateTracker : public Deprecated::IWorldSceneMouseTracker { private: class UndoRedoCommand; @@ -49,7 +49,7 @@ public: RadiographyLayerRotateTracker(UndoRedoStack& undoRedoStack, RadiographyScene& scene, - const ViewportGeometry& view, + const Deprecated::ViewportGeometry& view, size_t layer, double x, double y, @@ -69,7 +69,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Radiography/RadiographyScene.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyScene.cpp Tue May 21 13:25:58 2019 +0200 @@ -344,7 +344,7 @@ RadiographyLayer& RadiographyScene::LoadDicomImage(Orthanc::ImageAccessor* dicomImage, // takes ownership const std::string& instance, unsigned int frame, - DicomFrameConverter* converter, // takes ownership + Deprecated::DicomFrameConverter* converter, // takes ownership PhotometricDisplayMode preferredPhotometricDisplayMode, RadiographyLayer::Geometry* geometry) { @@ -364,7 +364,7 @@ return layer; } - RadiographyLayer& RadiographyScene::LoadDicomFrame(OrthancApiClient& orthanc, + RadiographyLayer& RadiographyScene::LoadDicomFrame(Deprecated::OrthancApiClient& orthanc, const std::string& instance, unsigned int frame, bool httpCompression, @@ -379,18 +379,18 @@ } { - IWebService::HttpHeaders headers; + Deprecated::IWebService::HttpHeaders headers; std::string uri = "/instances/" + instance + "/tags"; orthanc.GetBinaryAsync( uri, headers, - new Callable<RadiographyScene, OrthancApiClient::BinaryResponseReadyMessage> + new Callable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> (*this, &RadiographyScene::OnTagsReceived), NULL, new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); } { - IWebService::HttpHeaders headers; + Deprecated::IWebService::HttpHeaders headers; headers["Accept"] = "image/x-portable-arbitrarymap"; if (httpCompression) @@ -403,7 +403,7 @@ orthanc.GetBinaryAsync( uri, headers, - new Callable<RadiographyScene, OrthancApiClient::BinaryResponseReadyMessage> + new Callable<RadiographyScene, Deprecated::OrthancApiClient::BinaryResponseReadyMessage> (*this, &RadiographyScene::OnFrameReceived), NULL, new Orthanc::SingleValueObject<size_t>(layer.GetIndex())); } @@ -412,7 +412,7 @@ } - RadiographyLayer& RadiographyScene::LoadDicomWebFrame(IWebService& web) + RadiographyLayer& RadiographyScene::LoadDicomWebFrame(Deprecated::IWebService& web) { RadiographyLayer& layer = RegisterLayer(new RadiographyDicomLayer(IObservable::GetBroker(), *this)); @@ -422,7 +422,7 @@ - void RadiographyScene::OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) + void RadiographyScene::OnTagsReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) { size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&> (message.GetPayload()).GetValue(); @@ -452,7 +452,7 @@ } - void RadiographyScene::OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) + void RadiographyScene::OnFrameReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message) { size_t index = dynamic_cast<const Orthanc::SingleValueObject<size_t>&>(message.GetPayload()).GetValue(); @@ -726,7 +726,7 @@ } - void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, + void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, const Json::Value& dicomTags, const std::string& parentOrthancId, double pixelSpacingX, @@ -741,7 +741,7 @@ orthanc.PostJsonAsyncExpectJson( "/tools/create-dicom", createDicomRequestContent, - new Callable<RadiographyScene, OrthancApiClient::JsonResponseReadyMessage> + new Callable<RadiographyScene, Deprecated::OrthancApiClient::JsonResponseReadyMessage> (*this, &RadiographyScene::OnDicomExported), NULL, NULL); @@ -750,7 +750,7 @@ // Export using PAM is faster than using PNG, but requires Orthanc // core >= 1.4.3 - void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, + void RadiographyScene::ExportDicom(Deprecated::OrthancApiClient& orthanc, const Orthanc::DicomMap& dicom, const std::string& parentOrthancId, double pixelSpacingX, @@ -778,19 +778,19 @@ ExportDicom(orthanc, jsonTags, parentOrthancId, pixelSpacingX, pixelSpacingY, invert, interpolation, usePam); } - void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) + void RadiographyScene::OnDicomExported(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message) { LOG(INFO) << "DICOM export was successful: " << message.GetJson().toStyledString(); } - void RadiographyScene::OnDicomWebReceived(const IWebService::HttpRequestSuccessMessage& message) + void RadiographyScene::OnDicomWebReceived(const Deprecated::IWebService::HttpRequestSuccessMessage& message) { LOG(INFO) << "DICOMweb WADO-RS received: " << message.GetAnswerSize() << " bytes"; - const IWebService::HttpHeaders& h = message.GetAnswerHttpHeaders(); - for (IWebService::HttpHeaders::const_iterator + const Deprecated::IWebService::HttpHeaders& h = message.GetAnswerHttpHeaders(); + for (Deprecated::IWebService::HttpHeaders::const_iterator it = h.begin(); it != h.end(); ++it) { printf("[%s] = [%s]\n", it->first.c_str(), it->second.c_str());
--- a/Framework/Radiography/RadiographyScene.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyScene.h Tue May 21 13:25:58 2019 +0200 @@ -22,6 +22,7 @@ #pragma once #include "RadiographyLayer.h" +#include "../Toolbox/DicomFrameConverter.h" #include "../Toolbox/OrthancApiClient.h" #include "Framework/StoneEnumerations.h" #include "Core/Images/Image.h" @@ -30,7 +31,6 @@ namespace OrthancStone { class RadiographyDicomLayer; - class DicomFrameConverter; class RadiographyScene : public IObserver, @@ -149,13 +149,13 @@ protected: RadiographyLayer& RegisterLayer(RadiographyLayer* layer); - void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message); + void OnTagsReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message); - virtual void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message); + virtual void OnFrameReceived(const Deprecated::OrthancApiClient::BinaryResponseReadyMessage& message); - void OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message); + void OnDicomExported(const Deprecated::OrthancApiClient::JsonResponseReadyMessage& message); - void OnDicomWebReceived(const IWebService::HttpRequestSuccessMessage& message); + void OnDicomWebReceived(const Deprecated::IWebService::HttpRequestSuccessMessage& message); void OnLayerEdited(const RadiographyLayer::LayerEditedMessage& message); public: @@ -193,17 +193,17 @@ virtual RadiographyLayer& LoadDicomImage(Orthanc::ImageAccessor* dicomImage, // takes ownership const std::string& instance, unsigned int frame, - DicomFrameConverter* converter, // takes ownership + Deprecated::DicomFrameConverter* converter, // takes ownership PhotometricDisplayMode preferredPhotometricDisplayMode, RadiographyLayer::Geometry* geometry); - virtual RadiographyLayer& LoadDicomFrame(OrthancApiClient& orthanc, + virtual RadiographyLayer& LoadDicomFrame(Deprecated::OrthancApiClient& orthanc, const std::string& instance, unsigned int frame, bool httpCompression, RadiographyLayer::Geometry* geometry); // pass NULL if you want default geometry - RadiographyLayer& LoadDicomWebFrame(IWebService& web); + RadiographyLayer& LoadDicomWebFrame(Deprecated::IWebService& web); void RemoveLayer(size_t layerIndex); @@ -278,7 +278,7 @@ // Export using PAM is faster than using PNG, but requires Orthanc // core >= 1.4.3 - void ExportDicom(OrthancApiClient& orthanc, + void ExportDicom(Deprecated::OrthancApiClient& orthanc, const Orthanc::DicomMap& dicom, const std::string& parentOrthancId, double pixelSpacingX, @@ -287,7 +287,7 @@ ImageInterpolation interpolation, bool usePam); - void ExportDicom(OrthancApiClient& orthanc, + void ExportDicom(Deprecated::OrthancApiClient& orthanc, const Json::Value& dicomTags, const std::string& parentOrthancId, double pixelSpacingX,
--- a/Framework/Radiography/RadiographySceneReader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographySceneReader.cpp Tue May 21 13:25:58 2019 +0200 @@ -32,7 +32,7 @@ { void RadiographySceneBuilder::Read(const Json::Value& input, Orthanc::ImageAccessor* dicomImage /* takes ownership */, - DicomFrameConverter* dicomFrameConverter /* takes ownership */, + Deprecated::DicomFrameConverter* dicomFrameConverter /* takes ownership */, PhotometricDisplayMode preferredPhotometricDisplayMode ) {
--- a/Framework/Radiography/RadiographySceneReader.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographySceneReader.h Tue May 21 13:25:58 2019 +0200 @@ -26,13 +26,13 @@ #include "RadiographyDicomLayer.h" #include "RadiographyMaskLayer.h" #include "RadiographyTextLayer.h" +#include "../Toolbox/OrthancApiClient.h" + #include <json/value.h> #include <Core/Images/FontRegistry.h> namespace OrthancStone { - class OrthancApiClient; - // HACK: I had to introduce this builder class in order to be able to recreate a RadiographyScene // from a serialized scene that is passed to web-workers. // It needs some architecturing... @@ -42,7 +42,7 @@ RadiographyScene& scene_; const Orthanc::FontRegistry* fontRegistry_; std::auto_ptr<Orthanc::ImageAccessor> dicomImage_; - std::auto_ptr<DicomFrameConverter> dicomFrameConverter_; + std::auto_ptr<Deprecated::DicomFrameConverter> dicomFrameConverter_; PhotometricDisplayMode preferredPhotometricDisplayMode_; public: @@ -55,7 +55,7 @@ void Read(const Json::Value& input); void Read(const Json::Value& input, Orthanc::ImageAccessor* dicomImage, // takes ownership - DicomFrameConverter* dicomFrameConverter, // takes ownership + Deprecated::DicomFrameConverter* dicomFrameConverter, // takes ownership PhotometricDisplayMode preferredPhotometricDisplayMode ); @@ -72,10 +72,10 @@ class RadiographySceneReader : public RadiographySceneBuilder { - OrthancApiClient& orthancApiClient_; + Deprecated::OrthancApiClient& orthancApiClient_; public: - RadiographySceneReader(RadiographyScene& scene, OrthancApiClient& orthancApiClient) : + RadiographySceneReader(RadiographyScene& scene, Deprecated::OrthancApiClient& orthancApiClient) : RadiographySceneBuilder(scene), orthancApiClient_(orthancApiClient) {
--- a/Framework/Radiography/RadiographyWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -151,7 +151,7 @@ bool RadiographyWidget::RenderScene(CairoContext& context, - const ViewportGeometry& view) + const Deprecated::ViewportGeometry& view) { cairo_t* cr = context.GetObject();
--- a/Framework/Radiography/RadiographyWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyWidget.h Tue May 21 13:25:58 2019 +0200 @@ -30,7 +30,7 @@ class RadiographyMaskLayer; class RadiographyWidget : - public WorldSceneWidget, + public Deprecated::WorldSceneWidget, public IObserver { private: @@ -53,7 +53,7 @@ } virtual bool RenderScene(CairoContext& context, - const ViewportGeometry& view); + const Deprecated::ViewportGeometry& view); virtual void RenderBackground(Orthanc::ImageAccessor& image, float minValue, float maxValue);
--- a/Framework/Radiography/RadiographyWindowingTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyWindowingTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -164,8 +164,8 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches) + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches) { // This follows the behavior of the Osimis Web viewer: // https://bitbucket.org/osimis/osimis-webviewer-plugin/src/master/frontend/src/app/viewport/image-plugins/windowing-viewport-tool.class.js
--- a/Framework/Radiography/RadiographyWindowingTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Radiography/RadiographyWindowingTracker.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ namespace OrthancStone { - class RadiographyWindowingTracker : public IWorldSceneMouseTracker + class RadiographyWindowingTracker : public Deprecated::IWorldSceneMouseTracker { public: enum Action @@ -83,7 +83,7 @@ int displayY, double sceneX, double sceneY, - const std::vector<Touch>& displayTouches, - const std::vector<Touch>& sceneTouches); + const std::vector<Deprecated::Touch>& displayTouches, + const std::vector<Deprecated::Touch>& sceneTouches); }; }
--- a/Framework/Scene2D/IPointerTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/IPointerTracker.h Tue May 21 13:25:58 2019 +0200 @@ -21,6 +21,8 @@ #pragma once +#if 0 + #include "PointerEvent.h" namespace OrthancStone @@ -44,3 +46,5 @@ virtual void Release() = 0; }; } + +#endif
--- a/Framework/Scene2D/Internals/FixedPointAligner.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Internals/FixedPointAligner.cpp Tue May 21 13:25:58 2019 +0200 @@ -18,29 +18,31 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ - +#include <Framework/Scene2DViewport/ViewportController.h> #include "FixedPointAligner.h" namespace OrthancStone { namespace Internals { - FixedPointAligner::FixedPointAligner(Scene2D& scene, - const ScenePoint2D& p) : - scene_(scene), - canvas_(p) + FixedPointAligner::FixedPointAligner(ViewportControllerWPtr controllerW, + const ScenePoint2D& p) + : controllerW_(controllerW) + , canvas_(p) { - pivot_ = canvas_.Apply(scene_.GetCanvasToSceneTransform()); + ViewportControllerPtr controller = controllerW_.lock(); + pivot_ = canvas_.Apply(controller->GetCanvasToSceneTransform()); } void FixedPointAligner::Apply() { - ScenePoint2D p = canvas_.Apply(scene_.GetCanvasToSceneTransform()); + ViewportControllerPtr controller = controllerW_.lock(); + ScenePoint2D p = canvas_.Apply(controller->GetCanvasToSceneTransform()); - scene_.SetSceneToCanvasTransform( + controller->SetSceneToCanvasTransform( AffineTransform2D::Combine( - scene_.GetSceneToCanvasTransform(), + controller->GetSceneToCanvasTransform(), AffineTransform2D::CreateOffset(p.GetX() - pivot_.GetX(), p.GetY() - pivot_.GetY()))); }
--- a/Framework/Scene2D/Internals/FixedPointAligner.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Internals/FixedPointAligner.h Tue May 21 13:25:58 2019 +0200 @@ -18,11 +18,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ - #pragma once -#include "../Scene2D.h" -#include "../ScenePoint2D.h" +#include <Framework/Scene2DViewport/PointerTypes.h> +#include <Framework/Scene2D/ScenePoint2D.h> namespace OrthancStone { @@ -33,12 +32,12 @@ class FixedPointAligner : public boost::noncopyable { private: - Scene2D& scene_; - ScenePoint2D pivot_; - ScenePoint2D canvas_; + ViewportControllerWPtr controllerW_; + ScenePoint2D pivot_; + ScenePoint2D canvas_; public: - FixedPointAligner(Scene2D& scene, + FixedPointAligner(ViewportControllerWPtr controllerW, const ScenePoint2D& p); void Apply();
--- a/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp Tue May 21 13:25:58 2019 +0200 @@ -205,40 +205,40 @@ } // First triangle - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(-1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(1); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(-1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(1)); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); // Second triangle - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(1); - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(-1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(-1); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(1)); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(-1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(-1)); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); } }; @@ -247,7 +247,7 @@ const PolylineSceneLayer& layer) : context_(context), verticesCount_(0), - thickness_(layer.GetThickness()), + thickness_(static_cast<float>(layer.GetThickness())), red_(layer.GetRedAsFloat()), green_(layer.GetGreenAsFloat()), blue_(layer.GetBlueAsFloat()) @@ -418,12 +418,15 @@ double t1 = std::max(thickness, aliasingBorder); double t0 = std::max(0.0, thickness - aliasingBorder); - glUniform1f(program_->GetUniformLocation("u_thickness"), t1 / zoom); - glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), t0 / t1); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(t1 / zoom)); + glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), + static_cast<GLfloat>(t0 / t1)); } else { - glUniform1f(program_->GetUniformLocation("u_thickness"), thickness / zoom); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(thickness / zoom)); } } else @@ -433,12 +436,15 @@ double t1 = std::max(thickness, aliasingBorder / zoom); double t0 = std::max(0.0, thickness - aliasingBorder / zoom); - glUniform1f(program_->GetUniformLocation("u_thickness"), t1); - glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), t0 / t1); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(t1)); + glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), + static_cast<GLfloat>(t0 / t1)); } else { - glUniform1f(program_->GetUniformLocation("u_thickness"), thickness); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(thickness)); } } @@ -446,12 +452,14 @@ { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_TRIANGLES, 0, data.GetVerticesCount()); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetVerticesCount())); glDisable(GL_BLEND); } else { - glDrawArrays(GL_TRIANGLES, 0, data.GetVerticesCount()); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetVerticesCount())); } glDisableVertexAttribArray(locationPosition);
--- a/Framework/Scene2D/Internals/OpenGLTextProgram.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Internals/OpenGLTextProgram.cpp Tue May 21 13:25:58 2019 +0200 @@ -156,7 +156,8 @@ double dx, dy; // In pixels ComputeAnchorTranslation(dx, dy, data.GetAnchor(), - data.GetTextWidth(), data.GetTextHeight(), data.GetBorder()); + data.GetTextWidth(), data.GetTextHeight(), + static_cast<unsigned int>(data.GetBorder())); double x = data.GetX(); double y = data.GetY(); @@ -182,7 +183,8 @@ glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_TRIANGLES, 0, data.GetCoordinatesCount() / COMPONENTS); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetCoordinatesCount() / COMPONENTS)); glDisable(GL_BLEND); glDisableVertexAttribArray(positionLocation_);
--- a/Framework/Scene2D/PanSceneTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/PanSceneTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -20,27 +20,34 @@ #include "PanSceneTracker.h" +#include <Framework/Scene2DViewport/ViewportController.h> namespace OrthancStone { - PanSceneTracker::PanSceneTracker(Scene2D& scene, - const PointerEvent& event) : - scene_(scene), - originalSceneToCanvas_(scene_.GetSceneToCanvasTransform()), - originalCanvasToScene_(scene_.GetCanvasToSceneTransform()) + PanSceneTracker::PanSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event) + : OneGesturePointerTracker(controllerW) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) + , originalCanvasToScene_(GetController()->GetCanvasToSceneTransform()) { pivot_ = event.GetMainPosition().Apply(originalCanvasToScene_); } - void PanSceneTracker::Update(const PointerEvent& event) + void PanSceneTracker::PointerMove(const PointerEvent& event) { ScenePoint2D p = event.GetMainPosition().Apply(originalCanvasToScene_); - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( originalSceneToCanvas_, AffineTransform2D::CreateOffset(p.GetX() - pivot_.GetX(), p.GetY() - pivot_.GetY()))); } + + void PanSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } + }
--- a/Framework/Scene2D/PanSceneTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/PanSceneTracker.h Tue May 21 13:25:58 2019 +0200 @@ -21,27 +21,25 @@ #pragma once -#include "IPointerTracker.h" -#include "Scene2D.h" +#include "../Scene2DViewport/OneGesturePointerTracker.h" namespace OrthancStone { - class PanSceneTracker : public IPointerTracker + class ViewportController; + + class PanSceneTracker : public OneGesturePointerTracker { - private: - Scene2D& scene_; - ScenePoint2D pivot_; - AffineTransform2D originalSceneToCanvas_; - AffineTransform2D originalCanvasToScene_; - public: - PanSceneTracker(Scene2D& scene, + PanSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event); - virtual void Update(const PointerEvent& event); + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; - virtual void Release() - { - } + private: + ViewportControllerWPtr controllerW_; + ScenePoint2D pivot_; + AffineTransform2D originalSceneToCanvas_; + AffineTransform2D originalCanvasToScene_; }; }
--- a/Framework/Scene2D/RotateSceneTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/RotateSceneTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -18,23 +18,22 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ - #include "RotateSceneTracker.h" +#include <Framework/Scene2DViewport/ViewportController.h> namespace OrthancStone { - RotateSceneTracker::RotateSceneTracker(Scene2D& scene, - const PointerEvent& event) : - scene_(scene), - click_(event.GetMainPosition()), - aligner_(scene, click_), - isFirst_(true), - originalSceneToCanvas_(scene.GetSceneToCanvasTransform()) + RotateSceneTracker::RotateSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event) + : OneGesturePointerTracker(controllerW) + , click_(event.GetMainPosition()) + , aligner_(controllerW, click_) + , isFirst_(true) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) { } - - - void RotateSceneTracker::Update(const PointerEvent& event) + + void RotateSceneTracker::PointerMove(const PointerEvent& event) { ScenePoint2D p = event.GetMainPosition(); double dx = p.GetX() - click_.GetX(); @@ -51,7 +50,7 @@ isFirst_ = false; } - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( AffineTransform2D::CreateRotation(a - referenceAngle_), originalSceneToCanvas_)); @@ -59,4 +58,10 @@ aligner_.Apply(); } } + + void RotateSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } + }
--- a/Framework/Scene2D/RotateSceneTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/RotateSceneTracker.h Tue May 21 13:25:58 2019 +0200 @@ -21,29 +21,27 @@ #pragma once -#include "IPointerTracker.h" +#include "../Scene2DViewport/OneGesturePointerTracker.h" #include "Internals/FixedPointAligner.h" namespace OrthancStone { - class RotateSceneTracker : public IPointerTracker + class ViewportController; + + class RotateSceneTracker : public OneGesturePointerTracker { - private: - Scene2D& scene_; - ScenePoint2D click_; - Internals::FixedPointAligner aligner_; - double referenceAngle_; - bool isFirst_; - AffineTransform2D originalSceneToCanvas_; - public: - RotateSceneTracker(Scene2D& scene, + RotateSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event); - virtual void Update(const PointerEvent& event); + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; - virtual void Release() - { - } + private: + ScenePoint2D click_; + Internals::FixedPointAligner aligner_; + double referenceAngle_; + bool isFirst_; + AffineTransform2D originalSceneToCanvas_; }; }
--- a/Framework/Scene2D/Scene2D.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Scene2D.cpp Tue May 21 13:25:58 2019 +0200 @@ -76,8 +76,7 @@ Scene2D::Scene2D(const Scene2D& other) - : IObservable(other.GetBroker()) - , sceneToCanvas_(other.sceneToCanvas_) + : sceneToCanvas_(other.sceneToCanvas_) , canvasToScene_(other.canvasToScene_) , layerCounter_(0) { @@ -221,7 +220,6 @@ sceneToCanvas_ = transform; canvasToScene_ = inverse; - BroadcastMessage(SceneTransformChanged(*this)); } void Scene2D::FitContent(unsigned int canvasWidth,
--- a/Framework/Scene2D/Scene2D.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/Scene2D.h Tue May 21 13:25:58 2019 +0200 @@ -30,11 +30,9 @@ namespace OrthancStone { - class Scene2D : public IObservable + class Scene2D : public boost::noncopyable { public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SceneTransformChanged, Scene2D); - class IVisitor : public boost::noncopyable { public: @@ -60,9 +58,7 @@ Scene2D(const Scene2D& other); public: - Scene2D(MessageBroker& broker) - : IObservable(broker) - , layerCounter_(0) + Scene2D() : layerCounter_(0) { }
--- a/Framework/Scene2D/ZoomSceneTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/ZoomSceneTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -20,16 +20,17 @@ #include "ZoomSceneTracker.h" +#include <Framework/Scene2DViewport/ViewportController.h> namespace OrthancStone { - ZoomSceneTracker::ZoomSceneTracker(Scene2D& scene, + ZoomSceneTracker::ZoomSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event, - unsigned int canvasHeight) : - scene_(scene), - clickY_(event.GetMainPosition().GetY()), - aligner_(scene, event.GetMainPosition()), - originalSceneToCanvas_(scene.GetSceneToCanvasTransform()) + unsigned int canvasHeight) + : OneGesturePointerTracker(controllerW) + , clickY_(event.GetMainPosition().GetY()) + , aligner_(controllerW, event.GetMainPosition()) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) { if (canvasHeight <= 3) { @@ -42,8 +43,7 @@ } } - - void ZoomSceneTracker::Update(const PointerEvent& event) + void ZoomSceneTracker::PointerMove(const PointerEvent& event) { static const double MIN_ZOOM = -4; static const double MAX_ZOOM = 4; @@ -51,7 +51,10 @@ if (active_) { double y = event.GetMainPosition().GetY(); - double dy = static_cast<double>(y - clickY_) * normalization_; // In the range [-1,1] + + // In the range [-1,1] + double dy = static_cast<double>(y - clickY_) * normalization_; + double z; // Linear interpolation from [-1, 1] to [MIN_ZOOM, MAX_ZOOM] @@ -70,7 +73,7 @@ double zoom = pow(2.0, z); - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( AffineTransform2D::CreateScaling(zoom, zoom), originalSceneToCanvas_)); @@ -78,4 +81,9 @@ aligner_.Apply(); } } + + void ZoomSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } }
--- a/Framework/Scene2D/ZoomSceneTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Scene2D/ZoomSceneTracker.h Tue May 21 13:25:58 2019 +0200 @@ -21,30 +21,30 @@ #pragma once -#include "IPointerTracker.h" + +#include "../Scene2DViewport/OneGesturePointerTracker.h" #include "Internals/FixedPointAligner.h" namespace OrthancStone { - class ZoomSceneTracker : public IPointerTracker + class Scene2D; + + class ZoomSceneTracker : public OneGesturePointerTracker { + public: + ZoomSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event, + unsigned int canvasHeight); + + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; + private: - Scene2D& scene_; double clickY_; bool active_; double normalization_; Internals::FixedPointAligner aligner_; AffineTransform2D originalSceneToCanvas_; - public: - ZoomSceneTracker(Scene2D& scene, - const PointerEvent& event, - unsigned int canvasHeight); - - virtual void Update(const PointerEvent& event); - - virtual void Release() - { - } }; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,285 @@ +/** + * 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 "AngleMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include <Core/Logging.h> + +#include <boost/math/constants/constants.hpp> + +extern void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); + +namespace OrthancStone +{ + AngleMeasureTool::~AngleMeasureTool() + { + // this measuring tool is a RABI for the corresponding visual layers + // stored in the 2D scene + Disable(); + RemoveFromScene(); + } + + void AngleMeasureTool::RemoveFromScene() + { + if (layersCreated) + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textBaseZIndex_)); + GetScene()->DeleteLayer(polylineZIndex_); + GetScene()->DeleteLayer(textBaseZIndex_); + } + } + + void AngleMeasureTool::SetSide1End(ScenePoint2D pt) + { + side1End_ = pt; + RefreshScene(); + } + + void AngleMeasureTool::SetSide2End(ScenePoint2D pt) + { + side2End_ = pt; + RefreshScene(); + } + + void AngleMeasureTool::SetCenter(ScenePoint2D pt) + { + center_ = pt; + RefreshScene(); + } + + PolylineSceneLayer* AngleMeasureTool::GetPolylineLayer() + { + assert(GetScene()->HasLayer(polylineZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(polylineZIndex_)); + PolylineSceneLayer* concreteLayer = dynamic_cast<PolylineSceneLayer*>(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + void AngleMeasureTool::RefreshScene() + { + if (IsSceneAlive()) + { + + if (IsEnabled()) + { + // get the scaling factor + const double pixelToScene = + GetScene()->GetCanvasToSceneTransform().ComputeZoom(); + + if (!layersCreated) + { + // Create the layers if need be + + assert(textBaseZIndex_ == -1); + { + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + + } + { + textBaseZIndex_ = GetScene()->GetMaxDepth() + 100; + // create the four text background layers + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 1, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 2, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 3, layer.release()); + } + + // and the text layer itself + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_ + 4, layer.release()); + } + + } + layersCreated = true; + } + else + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textBaseZIndex_)); + } + { + // Fill the polyline layer with the measurement line + + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 183, 17); + + // sides + { + { + PolylineSceneLayer::Chain chain; + chain.push_back(side1End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + { + PolylineSceneLayer::Chain chain; + chain.push_back(side2End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + } + + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side1End_, 10.0 * pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side2End_, 10.0 * pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + } + + // arc + { + PolylineSceneLayer::Chain chain; + + const double ARC_RADIUS_CANVAS_COORD = 30.0; + AddShortestArc(chain, *GetScene(), side1End_, center_, side2End_, + ARC_RADIUS_CANVAS_COORD * pixelToScene); + polylineLayer->AddChain(chain, false); + } + } + { + // Set the text layer + + double p1cAngle = atan2( + side1End_.GetY() - center_.GetY(), + side1End_.GetX() - center_.GetX()); + + + double p2cAngle = atan2( + side2End_.GetY() - center_.GetY(), + side2End_.GetX() - center_.GetX()); + + double delta = NormalizeAngle(p2cAngle - p1cAngle); + + + double theta = p1cAngle + delta / 2; + + + const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; + + double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); + + double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); + + double pointX = center_.GetX() + offsetX * pixelToScene; + double pointY = center_.GetY() + offsetY * pixelToScene; + + char buf[64]; + double angleDeg = RadiansToDegrees(delta); + + // http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=00B0&mode=hex + sprintf(buf, "%0.02f\xc2\xb0", angleDeg); + + SetTextLayerOutlineProperties( + *GetScene(), textBaseZIndex_, buf, ScenePoint2D(pointX, pointY)); + + // TODO:make it togglable + bool enableInfoDisplay = false; + if (enableInfoDisplay) + { + TrackerSample_SetInfoDisplayMessage("center_.GetX()", + boost::lexical_cast<std::string>(center_.GetX())); + + TrackerSample_SetInfoDisplayMessage("center_.GetY()", + boost::lexical_cast<std::string>(center_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", + boost::lexical_cast<std::string>(side1End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", + boost::lexical_cast<std::string>(side1End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", + boost::lexical_cast<std::string>(side2End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", + boost::lexical_cast<std::string>(side2End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(p1cAngle))); + + TrackerSample_SetInfoDisplayMessage("delta (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(delta))); + + TrackerSample_SetInfoDisplayMessage("theta (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(theta))); + + TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(p2cAngle))); + + TrackerSample_SetInfoDisplayMessage("offsetX (pix)", + boost::lexical_cast<std::string>(offsetX)); + + TrackerSample_SetInfoDisplayMessage("offsetY (pix)", + boost::lexical_cast<std::string>(offsetY)); + + TrackerSample_SetInfoDisplayMessage("pointX", + boost::lexical_cast<std::string>(pointX)); + + TrackerSample_SetInfoDisplayMessage("pointY", + boost::lexical_cast<std::string>(pointY)); + + TrackerSample_SetInfoDisplayMessage("angleDeg", + boost::lexical_cast<std::string>(angleDeg)); + } + + + + } + } + else + { + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,76 @@ +/** + * 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 "MeasureTools.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +namespace OrthancStone +{ + class AngleMeasureTool : public MeasureTool + { + public: + AngleMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layersCreated(false) + , polylineZIndex_(-1) + , textBaseZIndex_(-1) + { + + } + + ~AngleMeasureTool(); + + void SetSide1End(ScenePoint2D start); + void SetCenter(ScenePoint2D start); + void SetSide2End(ScenePoint2D start); + + private: + PolylineSceneLayer* GetPolylineLayer(); + + // 0 --> 3 are for the text background (outline) + // 4 is for the actual text + TextSceneLayer* GetTextLayer(int index); + virtual void RefreshScene() ORTHANC_OVERRIDE; + void RemoveFromScene(); + + private: + ScenePoint2D side1End_; + ScenePoint2D side2End_; + ScenePoint2D center_; + bool layersCreated; + int polylineZIndex_; + int textBaseZIndex_; + }; + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,127 @@ +/** + * 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 "CreateAngleMeasureTracker.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateAngleMeasureTracker::CreateAngleMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + const PointerEvent& e) + : CreateMeasureTracker(controllerW) + , state_(CreatingSide1) + { + command_.reset( + new CreateAngleMeasureCommand( + broker, + controllerW, + e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + } + + CreateAngleMeasureTracker::~CreateAngleMeasureTracker() + { + } + + void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) + { + assert(GetScene()); + + if (!alive_) + { + throw OrthancException(ErrorCode_InternalError, + "Internal error: wrong state in CreateAngleMeasureTracker::" + "PointerMove: active_ == false"); + } + + ScenePoint2D scenePos = event.GetMainPosition().Apply( + GetScene()->GetCanvasToSceneTransform()); + + switch (state_) + { + case CreatingSide1: + GetCommand()->SetCenter(scenePos); + break; + case CreatingSide2: + GetCommand()->SetSide2End(scenePos); + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << + // "scenePos.GetY() = " << scenePos.GetY(); + } + + void CreateAngleMeasureTracker::PointerUp(const PointerEvent& e) + { + // TODO: the current app does not prevent multiple PointerDown AND + // PointerUp to be sent to the tracker. + // Unless we augment the PointerEvent structure with the button index, + // we cannot really tell if this pointer up event matches the initial + // pointer down event. Let's make it simple for now. + + switch (state_) + { + case CreatingSide1: + state_ = CreatingSide2; + break; + case CreatingSide2: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerUp: state_ == CreatingSide2 ; this should not happen"); + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + } + + void CreateAngleMeasureTracker::PointerDown(const PointerEvent& e) + { + switch (state_) + { + case CreatingSide1: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerDown: state_ == CreatingSide1 ; this should not happen"); + break; + case CreatingSide2: + // we are done + alive_ = false; + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + } + + CreateAngleMeasureCommandPtr CreateAngleMeasureTracker::GetCommand() + { + return boost::dynamic_pointer_cast<CreateAngleMeasureCommand>(command_); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,63 @@ +/** + * 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 "MeasureTrackers.h" +#include "MeasureCommands.h" + +#include <vector> + +namespace OrthancStone +{ + class CreateAngleMeasureTracker : public CreateMeasureTracker + { + public: + /** + When you create this tracker, you need to supply it with the undo stack + where it will store the commands that perform the actual measure tool + creation and modification. + In turn, a container for these commands to store the actual measuring + must be supplied, too + */ + CreateAngleMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + const PointerEvent& e); + + ~CreateAngleMeasureTracker(); + + virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; + + private: + CreateAngleMeasureCommandPtr GetCommand(); + + enum State + { + CreatingSide1, + CreatingSide2, + Finished // just for debug + }; + State state_; + + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,90 @@ +/** + * 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 "CreateLineMeasureTracker.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateLineMeasureTracker::CreateLineMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + const PointerEvent& e) + : CreateMeasureTracker(controllerW) + { + command_.reset( + new CreateLineMeasureCommand( + broker, + controllerW, + e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + } + + CreateLineMeasureTracker::~CreateLineMeasureTracker() + { + + } + + void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) + { + assert(GetScene()); + + if (!alive_) + { + throw OrthancException(ErrorCode_InternalError, + "Internal error: wrong state in CreateLineMeasureTracker::" + "PointerMove: active_ == false"); + } + + ScenePoint2D scenePos = event.GetMainPosition().Apply( + GetScene()->GetCanvasToSceneTransform()); + + //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << + // "scenePos.GetY() = " << scenePos.GetY(); + + CreateLineMeasureTracker* concreteThis = + dynamic_cast<CreateLineMeasureTracker*>(this); + assert(concreteThis != NULL); + GetCommand()->SetEnd(scenePos); + } + + void CreateLineMeasureTracker::PointerUp(const PointerEvent& e) + { + // TODO: the current app does not prevent multiple PointerDown AND + // PointerUp to be sent to the tracker. + // Unless we augment the PointerEvent structure with the button index, + // we cannot really tell if this pointer up event matches the initial + // pointer down event. Let's make it simple for now. + alive_ = false; + } + + void CreateLineMeasureTracker::PointerDown(const PointerEvent& e) + { + LOG(WARNING) << "Additional touches (fingers, pen, mouse buttons...) " + "are ignored when the line measure creation tracker is active"; + } + + CreateLineMeasureCommandPtr CreateLineMeasureTracker::GetCommand() + { + return boost::dynamic_pointer_cast<CreateLineMeasureCommand>(command_); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h Tue May 21 13:25:58 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 "MeasureTrackers.h" + +namespace OrthancStone +{ + class CreateLineMeasureTracker : public CreateMeasureTracker + { + public: + /** + When you create this tracker, you need to supply it with the undo stack + where it will store the commands that perform the actual measure tool + creation and modification. + In turn, a container for these commands to store the actual measuring + must be supplied, too + */ + CreateLineMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + const PointerEvent& e); + + ~CreateLineMeasureTracker(); + + virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; + + private: + CreateLineMeasureCommandPtr GetCommand(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,20 @@ +/** + * 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/>. + **/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,22 @@ +/** + * 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 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,79 @@ +/** + * 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 "IFlexiblePointerTracker.h" +#include <Framework/Scene2D/IPointerTracker.h> + + +namespace OrthancStone +{ +#if 0 + namespace + { + class SimpleTrackerAdapter : public IFlexiblePointerTracker + { + public: + SimpleTrackerAdapter(PointerTrackerPtr wrappedTracker) + : wrappedTracker_(wrappedTracker) + , active_(true) + { + } + + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE + { + if(active_) + wrappedTracker_->Update(event); + }; + virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE + { + if (wrappedTracker_) + { + wrappedTracker_->Release(); + wrappedTracker_ = NULL; + } + active_ = false; + } + virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE + { + // nothing to do atm + } + virtual bool IsActive() const ORTHANC_OVERRIDE + { + return active_; + } + + virtual void Cancel() ORTHANC_OVERRIDE + { + wrappedTracker_ = NULL; + active_ = false; + } + + private: + PointerTrackerPtr wrappedTracker_; + bool active_; + }; + } + + FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr t) + { + return FlexiblePointerTrackerPtr(new SimpleTrackerAdapter(t)); + } +#endif +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/IFlexiblePointerTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,87 @@ +/** + * 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 "PointerTypes.h" + +#include <Framework/Scene2D/PointerEvent.h> + +namespace OrthancStone +{ + /** + This interface represents a flexible mouse tracker that can respond to + several events and is not automatically deleted upon mouse up or when touch + interaction is suspended : for instance, a stateful tracker with a two-step + interaction like: click & drag --> mouse up --> drag --> mouse click + (for instance, for an angle measuring tracker or an ellipse tracker) + */ + class IFlexiblePointerTracker : public boost::noncopyable + { + public: + virtual ~IFlexiblePointerTracker() {} + + /** + This method will be repeatedly called during user interaction + */ + virtual void PointerMove(const PointerEvent& event) = 0; + + /** + This method will be called when a touch/pointer is removed (mouse up, + pen lift, finger removed...) + */ + virtual void PointerUp(const PointerEvent& event) = 0; + + /** + This method will be called when a touch/pointer is added (mouse down, + pen or finger press) + + Important note: the initial pointer down that leads to creating the + tracker is NOT sent to the tracker. + + Thus, if you count the PointerDown vs PointerUp, there will be an extra + PointerUp. + */ + virtual void PointerDown(const PointerEvent& event) = 0; + + /** + This method will be repeatedly called by the tracker owner (for instance, + the application) to check whether the tracker must keep on receiving + interaction or if its job is done and it should be deleted. + */ + virtual bool IsAlive() const = 0; + + /** + This will be called if the tracker needs to be dismissed without committing + its changes to the underlying model. If the model has been modified during + tracker lifetime, it must be restored to its initial value + */ + virtual void Cancel() = 0; + }; + + + /** + This factory adopts the supplied simple tracker and creates a flexible + tracker wrapper around it. + */ + FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,201 @@ +/** + * 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 "LineMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include <Core/Logging.h> + + +namespace OrthancStone +{ + LineMeasureTool::~LineMeasureTool() + { + // this measuring tool is a RABI for the corresponding visual layers + // stored in the 2D scene + Disable(); + RemoveFromScene(); + } + + void LineMeasureTool::RemoveFromScene() + { + if (layersCreated) + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textZIndex_)); + GetScene()->DeleteLayer(polylineZIndex_); + GetScene()->DeleteLayer(textZIndex_); + } + } + + + void LineMeasureTool::SetStart(ScenePoint2D start) + { + start_ = start; + RefreshScene(); + } + + void LineMeasureTool::SetEnd(ScenePoint2D end) + { + end_ = end; + RefreshScene(); + } + + void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end) + { + start_ = start; + end_ = end; + RefreshScene(); + } + + PolylineSceneLayer* LineMeasureTool::GetPolylineLayer() + { + assert(GetScene()->HasLayer(polylineZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(polylineZIndex_)); + PolylineSceneLayer* concreteLayer = dynamic_cast<PolylineSceneLayer*>(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + TextSceneLayer* LineMeasureTool::GetTextLayer() + { + assert(GetScene()->HasLayer(textZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(textZIndex_)); + TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + void LineMeasureTool::RefreshScene() + { + if (IsSceneAlive()) + { + if (IsEnabled()) + { + if (!layersCreated) + { + // Create the layers if need be + + assert(textZIndex_ == -1); + { + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + } + { + textZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textZIndex_, layer.release()); + } + layersCreated = true; + } + else + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textZIndex_)); + } + { + // Fill the polyline layer with the measurement line + + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 223, 21); + + { + PolylineSceneLayer::Chain chain; + chain.push_back(start_); + chain.push_back(end_); + polylineLayer->AddChain(chain, false); + } + + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), start_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), end_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + //ScenePoint2D startC = start_.Apply(GetScene()->GetSceneToCanvasTransform()); + //double squareSize = 10.0; + //double startHandleLX = startC.GetX() - squareSize/2; + //double startHandleTY = startC.GetY() - squareSize / 2; + //double startHandleRX = startC.GetX() + squareSize / 2; + //double startHandleBY = startC.GetY() + squareSize / 2; + //ScenePoint2D startLTC(startHandleLX, startHandleTY); + //ScenePoint2D startRTC(startHandleRX, startHandleTY); + //ScenePoint2D startRBC(startHandleRX, startHandleBY); + //ScenePoint2D startLBC(startHandleLX, startHandleBY); + + //ScenePoint2D startLT = startLTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRT = startRTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRB = startRBC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startLB = startLBC.Apply(GetScene()->GetCanvasToSceneTransform()); + + //PolylineSceneLayer::Chain chain; + //chain.push_back(startLT); + //chain.push_back(startRT); + //chain.push_back(startRB); + //chain.push_back(startLB); + //polylineLayer->AddChain(chain, true); + } + + } + { + // Set the text layer proporeties + + TextSceneLayer* textLayer = GetTextLayer(); + double deltaX = end_.GetX() - start_.GetX(); + double deltaY = end_.GetY() - start_.GetY(); + double squareDist = deltaX * deltaX + deltaY * deltaY; + double dist = sqrt(squareDist); + char buf[64]; + sprintf(buf, "%0.02f units", dist); + textLayer->SetText(buf); + textLayer->SetColor(0, 223, 21); + + // TODO: for now we simply position the text overlay at the middle + // of the measuring segment + double midX = 0.5 * (end_.GetX() + start_.GetX()); + double midY = 0.5 * (end_.GetY() + start_.GetY()); + textLayer->SetPosition(midX, midY); + } + } + else + { + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } + } + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,71 @@ +/** + * 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 "MeasureTools.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +namespace OrthancStone +{ + class LineMeasureTool : public MeasureTool + { + public: + LineMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layersCreated(false) + , polylineZIndex_(-1) + , textZIndex_(-1) + { + + } + + ~LineMeasureTool(); + + void SetStart(ScenePoint2D start); + void SetEnd(ScenePoint2D end); + void Set(ScenePoint2D start, ScenePoint2D end); + + private: + PolylineSceneLayer* GetPolylineLayer(); + TextSceneLayer* GetTextLayer(); + virtual void RefreshScene() ORTHANC_OVERRIDE; + void RemoveFromScene(); + + private: + ScenePoint2D start_; + ScenePoint2D end_; + bool layersCreated; + int polylineZIndex_; + int textZIndex_; + }; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,100 @@ +/** + * 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 "MeasureCommands.h" + +#include <boost/make_shared.hpp> +#include <boost/ref.hpp> + +namespace OrthancStone +{ + void CreateMeasureCommand::Undo() + { + // simply disable the measure tool upon undo + GetController()->RemoveMeasureTool(GetMeasureTool()); + } + + void CreateMeasureCommand::Redo() + { + GetController()->AddMeasureTool(GetMeasureTool()); + } + + CreateMeasureCommand::CreateMeasureCommand(ViewportControllerWPtr controllerW) + : TrackerCommand(controllerW) + { + + } + + CreateMeasureCommand::~CreateMeasureCommand() + { + // deleting the command should not change the model state + // we thus leave it as is + } + + CreateLineMeasureCommand::CreateLineMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr 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); + } + + CreateAngleMeasureCommand::CreateAngleMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr 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); + } + + ViewportControllerPtr TrackerCommand::GetController() + { + ViewportControllerPtr controller = controllerW_.lock(); + assert(controller); // accessing dead object? + return controller; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,106 @@ +/** + * 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 <Framework/Scene2D/Scene2D.h> +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +// to be moved into Stone +#include "PointerTypes.h" +#include "MeasureTools.h" +#include "LineMeasureTool.h" +#include "AngleMeasureTool.h" + +namespace OrthancStone +{ + class TrackerCommand : public boost::noncopyable + { + public: + TrackerCommand(ViewportControllerWPtr controllerW) + : controllerW_(controllerW) + { + + } + virtual void Undo() = 0; + virtual void Redo() = 0; + + protected: + ViewportControllerPtr GetController(); + ViewportControllerWPtr controllerW_; + }; + + class CreateMeasureCommand : public TrackerCommand + { + public: + CreateMeasureCommand(ViewportControllerWPtr controllerW); + ~CreateMeasureCommand(); + virtual void Undo() ORTHANC_OVERRIDE; + virtual void Redo() ORTHANC_OVERRIDE; + private: + /** Must be implemented by the subclasses that create the actual tool */ + virtual MeasureToolPtr GetMeasureTool() = 0; + }; + + class CreateLineMeasureCommand : public CreateMeasureCommand + { + public: + CreateLineMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + ScenePoint2D point); + + // the starting position is set in the ctor + void SetEnd(ScenePoint2D scenePos); + + private: + virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE + { + return measureTool_; + } + LineMeasureToolPtr measureTool_; + }; + + + class CreateAngleMeasureCommand : public CreateMeasureCommand + { + public: + /** Ctor sets end of side 1*/ + CreateAngleMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + ScenePoint2D point); + + /** This method sets center*/ + void SetCenter(ScenePoint2D scenePos); + + /** This method sets end of side 2*/ + void SetSide2End(ScenePoint2D scenePos); + + private: + virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE + { + return measureTool_; + } + AngleMeasureToolPtr measureTool_; + }; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,97 @@ +/** + * 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 "MeasureTools.h" + +#include <Core/Logging.h> +#include <Core/Enumerations.h> +#include <Core/OrthancException.h> + +#include <boost/math/constants/constants.hpp> + +using namespace Orthanc; + +namespace OrthancStone +{ + + MeasureTool::~MeasureTool() + { + + } + + void MeasureTool::Enable() + { + enabled_ = true; + RefreshScene(); + } + + void MeasureTool::Disable() + { + enabled_ = false; + RefreshScene(); + } + + bool MeasureTool::IsEnabled() const + { + return enabled_; + } + + + ViewportControllerPtr MeasureTool::GetController() + { + ViewportControllerPtr controller = controllerW_.lock(); + if (!controller) + throw OrthancException(ErrorCode_InternalError, + "Using dead ViewportController object!"); + return controller; + } + + OrthancStone::Scene2DPtr MeasureTool::GetScene() + { + return GetController()->GetScene(); + } + + MeasureTool::MeasureTool(MessageBroker& broker, + ViewportControllerWPtr controllerW) + : IObserver(broker) + , controllerW_(controllerW) + , enabled_(true) + { + GetController()->RegisterObserverCallback( + new Callable<MeasureTool, ViewportController::SceneTransformChanged> + (*this, &MeasureTool::OnSceneTransformChanged)); + } + + + bool MeasureTool::IsSceneAlive() const + { + ViewportControllerPtr controller = controllerW_.lock(); + return (controller.get() != NULL); + } + + void MeasureTool::OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message) + { + RefreshScene(); + } + + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,98 @@ +/** + * 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 <Framework/Scene2DViewport/PointerTypes.h> +#include <Framework/Scene2DViewport/ViewportController.h> + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +namespace OrthancStone +{ + class MeasureTool : public IObserver + { + public: + virtual ~MeasureTool(); + + /** + Enabled tools are rendered in the scene. + */ + void Enable(); + + /** + Disabled tools are not rendered in the scene. This is useful to be able + to use them as their own memento in command stacks (when a measure tool + creation command has been undone, the measure remains alive in the + command object but is disabled so that it can be redone later on easily) + */ + void Disable(); + + /** + This method is called when the scene transform changes. It allows to + recompute the visual elements whose content depend upon the scene transform + */ + void OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message); + + protected: + MeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW); + + /** + The measuring tool may exist in a standalone fashion, without any available + scene (because the controller is dead or dying). This call allows to check + before accessing the scene. + */ + bool IsSceneAlive() const; + + /** + This is the meat of the tool: this method must [create (if needed) and] + update the layers and their data according to the measure tool kind and + current state. This is repeatedly called during user interaction + */ + virtual void RefreshScene() = 0; + + ViewportControllerPtr GetController(); + Scene2DPtr GetScene(); + + /** + enabled_ is not accessible by subclasses because there is a state machine + that we do not wanna mess with + */ + bool IsEnabled() const; + + private: + ViewportControllerWPtr controllerW_; + bool enabled_; + }; +} + + +extern void TrackerSample_SetInfoDisplayMessage( + std::string key, std::string value);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,336 @@ +/** + * 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 "MeasureToolsToolbox.h" + +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/math/constants/constants.hpp> + +namespace +{ + double g_pi = boost::math::constants::pi<double>(); +} + +namespace OrthancStone +{ + double RadiansToDegrees(double angleRad) + { + static const double factor = 180.0 / g_pi; + return angleRad * factor; + } + + void AddSquare(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& sideLength) + { + chain.clear(); + chain.reserve(4); + ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + double handleLX = centerC.GetX() - sideLength / 2; + double handleTY = centerC.GetY() - sideLength / 2; + double handleRX = centerC.GetX() + sideLength / 2; + double handleBY = centerC.GetY() + sideLength / 2; + ScenePoint2D LTC(handleLX, handleTY); + ScenePoint2D RTC(handleRX, handleTY); + ScenePoint2D RBC(handleRX, handleBY); + ScenePoint2D LBC(handleLX, handleBY); + + ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); + + chain.push_back(startLT); + chain.push_back(startRT); + chain.push_back(startRB); + chain.push_back(startLB); + } +#if 0 + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const bool clockwise + , const int subdivisionsCount) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + AddArc( + chain, scene, c, radiusS, p1cAngle, p2cAngle, + clockwise, subdivisionsCount); + } +#endif + + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const int subdivisionsCount) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + AddShortestArc( + chain, scene, c, radiusS, p1cAngle, p2cAngle, subdivisionsCount); + } + + void GetPositionOnBisectingLine( + ScenePoint2D& result + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double d) + { + // TODO: fix correct half-plane + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + double angle = 0.5*(p1cAngle + p2cAngle); + double unitVectorX = cos(angle); + double unitVectorY = sin(angle); + double posX = c.GetX() + d * unitVectorX; + double posY = c.GetX() + d * unitVectorY; + result = ScenePoint2D(posX, posY); + } + + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const int subdivisionsCount) + { + // this gives a signed difference between angle which + // is the smallest difference (in magnitude) between + // the angles + double delta = NormalizeAngle(endAngleRad-startAngleRad); + + chain.clear(); + chain.reserve(subdivisionsCount + 1); + + double angleIncr = delta/static_cast<double>(subdivisionsCount); + + double theta = startAngleRad; + for (int i = 0; i < subdivisionsCount + 1; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } + +#if 0 + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const bool clockwise + , const int subdivisionsCount) + { + double startAngleRadN = NormalizeAngle(startAngleRad); + double endAngleRadN = NormalizeAngle(endAngleRad); + + double angle1Rad = std::min(startAngleRadN, endAngleRadN); + double angle2Rad = std::max(startAngleRadN, endAngleRadN); + + // now we are sure angle1Rad < angle2Rad + // this means that if we draw from 1 to 2, it will be clockwise ( + // increasing angles). + // let's fix this: + if (!clockwise) + { + angle2Rad -= 2 * g_pi; + // now we are sure angle2Rad < angle1Rad (since they were normalized) + // and, thus, going from 1 to 2 means the angle values will DECREASE, + // which is the definition of anticlockwise + } + + chain.clear(); + chain.reserve(subdivisionsCount + 1); + + double angleIncr = (angle2Rad - angle1Rad) + / static_cast<double>(subdivisionsCount); + + double theta = angle1Rad; + for (int i = 0; i < subdivisionsCount + 1; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } +#endif + + void AddCircle(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& radiusS, + const int numSubdivisions) + { + //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + + // TODO: automatically compute the number for segments for smooth + // display based on the radius in pixels. + + chain.clear(); + chain.reserve(numSubdivisions); + + double angleIncr = (2.0 * g_pi) + / static_cast<double>(numSubdivisions); + + double theta = 0; + for (int i = 0; i < numSubdivisions; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } + + double NormalizeAngle(double angle) + { + double retAngle = angle; + while (retAngle < -1.0*g_pi) + retAngle += 2 * g_pi; + while (retAngle >= g_pi) + retAngle -= 2 * g_pi; + return retAngle; + } + + double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + double delta = p2cAngle - p1cAngle; + return NormalizeAngle(delta); + } + + +#if 0 + void AddEllipse(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& halfHAxis, + const double& halfVAxis) + { + chain.clear(); + chain.reserve(4); + ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + double handleLX = centerC.GetX() - sideLength / 2; + double handleTY = centerC.GetY() - sideLength / 2; + double handleRX = centerC.GetX() + sideLength / 2; + double handleBY = centerC.GetY() + sideLength / 2; + ScenePoint2D LTC(handleLX, handleTY); + ScenePoint2D RTC(handleRX, handleTY); + ScenePoint2D RBC(handleRX, handleBY); + ScenePoint2D LBC(handleLX, handleBY); + + ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); + + chain.push_back(startLT); + chain.push_back(startRT); + chain.push_back(startRB); + chain.push_back(startLB); +} +#endif + + + namespace + { + /** + Helper function for outlined text rendering + */ + TextSceneLayer* GetOutlineTextLayer( + Scene2D& scene, int baseLayerIndex, int index) + { + assert(scene.HasLayer(baseLayerIndex)); + assert(index >= 0); + assert(index < 5); + + ISceneLayer * layer = &(scene.GetLayer(baseLayerIndex + index)); + TextSceneLayer * concreteLayer = dynamic_cast<TextSceneLayer*>(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + } + + void SetTextLayerOutlineProperties( + Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p) + { + double xoffsets[5] = { 2, 0, -2, 0, 0 }; + double yoffsets[5] = { 0, -2, 0, 2, 0 }; + + // get the scaling factor + const double pixelToScene = + scene.GetCanvasToSceneTransform().ComputeZoom(); + + for (int i = 0; i < 5; ++i) + { + TextSceneLayer* textLayer = GetOutlineTextLayer(scene, baseLayerIndex, i); + textLayer->SetText(text); + + if (i == 4) + textLayer->SetColor(0, 223, 81); + else + textLayer->SetColor(0, 56, 21); + + ScenePoint2D textAnchor; + //GetPositionOnBisectingLine( + // textAnchor, side1End_, center_, side2End_, 40.0*pixelToScene); + textLayer->SetPosition( + p.GetX() + xoffsets[i] * pixelToScene, + p.GetY() + yoffsets[i] * pixelToScene); + } + } + + + + + + + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,187 @@ +/** + * 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 <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/Scene2D.h> + +namespace OrthancStone +{ + + /** + This function will create a square around the center point supplied in + scene coordinates, with a side length given in canvas coordinates. The + square sides are parallel to the canvas boundaries. + */ + void AddSquare(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& sideLength); + + + /** + Creates an arc centered on c that goes + - from a point r1: + - so that r1 belongs to the p1,c line + - so that the distance from c to r1 equals radius + - to a point r2: + - so that r2 belongs to the p2,c line + - so that the distance from c to r2 equals radius + - that follows the shortest among the two possible paths + + Warning: the existing chain content will be wiped out. + */ + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const int subdivisionsCount = 63); + + /** + Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from + start angle to end angle, by following the shortest arc. + + Warning: the existing chain content will be wiped out. + */ + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const int subdivisionsCount = 63); + +#if 0 + /** + Creates an arc centered on c that goes + - from a point r1: + - so that r1 belongs to the p1,c line + - so that the distance from c to r1 equals radius + - to a point r2: + - so that r2 belongs to the p2,c line + - so that the distance from c to r2 equals radius + + if clockwise is true, the arc is drawn from r1 to r2 with increasing + angle values. Otherwise, the angle values decrease. + + Warning: the existing chain content will be wiped out. + */ + + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const bool clockwise + , const int subdivisionsCount = 63); + + /** + Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from + start angle to end angle with the supplied radius. + + if clockwise is true, the arc is drawn from start to end by increasing the + angle values. + + Otherwise, the angle value decreases from start to end. + + Warning: the existing chain content will be wiped out. + */ + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const bool clockwise + , const int subdivisionsCount = 63); +#endif + /** + Creates a circle (closed curve) with "numSubdivisions" + (N points) + + Warning: the existing chain content will be wiped out. + */ + void AddCircle(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& radiusS, + const int numSubdivisions = 63); + + /** + Adds or subtracts 2*pi as many times as need to shift the specified + angle to a value such as: -pi <= value < pi + */ + double NormalizeAngle(double angle); + + /** + Returns the angle magnitude between the p1,c and p2,c lines. + The returned angle is between 0 and 2*pi + + If the angle is between 0 and pi, this means that the shortest arc + from p1 to p2 is clockwise. + + If the angle is between pi and 2*pi, this means that the shortest arc + from p1 to p2 is COUNTERclockwise. + + */ + double MeasureAngle( + const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2); + + /** + RadiansToDegrees + */ + double RadiansToDegrees(double angleRad); + + /** + This function will return the coordinates of a point that: + - belongs to the two bisecting lines of the p1 c p2 angle. + - is a distance d from c. + Among the four possible points, the one returned will be the one belonging + to the *smallest* half-plane defined by the [c,p1[ and [c,p2[ half-lines. + */ + void GetPositionOnBisectingLine( + ScenePoint2D& result + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double d); + + + /** + This helper is used when drawing text with an outline. + It set the properties for several text layers at once : first the + four outline layers, with a position shift and then the actual main text + layer. + + The five text layers are supposed to already exist in the scene, starting + from layerIndex, up to (and not including) layerIndex+5. + */ + void SetTextLayerOutlineProperties( + Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,66 @@ +/** + * 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 "MeasureTrackers.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + + CreateMeasureTracker::CreateMeasureTracker(ViewportControllerWPtr controllerW) + : controllerW_(controllerW) + , alive_(true) + , commitResult_(true) + { + } + + void CreateMeasureTracker::Cancel() + { + commitResult_ = false; + alive_ = false; + } + + bool CreateMeasureTracker::IsAlive() const + { + return alive_; + } + + CreateMeasureTracker::~CreateMeasureTracker() + { + // if the tracker completes successfully, we add the command + // to the undo stack + + // otherwise, we simply undo it + if (commitResult_) + controllerW_.lock()->PushCommand(command_); + else + command_->Undo(); + } + + OrthancStone::Scene2DPtr CreateMeasureTracker::GetScene() + { + return controllerW_.lock()->GetScene(); + } + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,54 @@ +/** + * 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 "IFlexiblePointerTracker.h" +#include "../../Framework/Scene2D/Scene2D.h" +#include "../../Framework/Scene2D/PointerEvent.h" + +#include "MeasureTools.h" +#include "MeasureCommands.h" + +#include <vector> + +namespace OrthancStone +{ + class CreateMeasureTracker : public IFlexiblePointerTracker + { + public: + virtual void Cancel() ORTHANC_OVERRIDE; + virtual bool IsAlive() const ORTHANC_OVERRIDE; + protected: + CreateMeasureTracker(ViewportControllerWPtr controllerW); + + ~CreateMeasureTracker(); + + protected: + CreateMeasureCommandPtr command_; + ViewportControllerWPtr controllerW_; + bool alive_; + Scene2DPtr GetScene(); + + private: + bool commitResult_; + }; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,71 @@ +/** + * 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 "OneGesturePointerTracker.h" + +#include <Core/OrthancException.h> + +#include <Framework/StoneException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + OneGesturePointerTracker::OneGesturePointerTracker( + ViewportControllerWPtr controllerW) + : controllerW_(controllerW) + , alive_(true) + , currentTouchCount_(1) + { + } + + void OneGesturePointerTracker::PointerUp(const PointerEvent& event) + { + // pointer up is only called for the LAST up event in case of a multi-touch + // gesture + ORTHANC_ASSERT(currentTouchCount_ > 0, "Wrong state in tracker"); + currentTouchCount_--; + LOG(INFO) << "currentTouchCount_ becomes: " << currentTouchCount_; + if (currentTouchCount_ == 0) + { + LOG(INFO) << "currentTouchCount_ == 0 --> alive_ = false"; + alive_ = false; + } + } + + void OneGesturePointerTracker::PointerDown(const PointerEvent& event) + { + // additional touches are not taken into account but we need to count + // the number of active touches + currentTouchCount_++; + LOG(INFO) << "currentTouchCount_ becomes: " << currentTouchCount_; + } + + bool OneGesturePointerTracker::IsAlive() const + { + return alive_; + } + + ViewportControllerPtr OneGesturePointerTracker::GetController() + { + return controllerW_.lock(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,56 @@ +/** + * 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 "IFlexiblePointerTracker.h" + +namespace OrthancStone +{ + /** + This base is class allows to write simple trackers that deal with single + drag gestures with only one touch. It is *not* suitable for multi-touch and + multi-state trackers where various mouse operations need to be handled. + + In order to write such a tracker: + - subclass this class + - you may store the initial click/touch position in the constructor + - implement PointerMove to react to pointer/touch events + - implement Cancel to restore the state at initial tracker creation time + + */ + class OneGesturePointerTracker : public IFlexiblePointerTracker + { + public: + OneGesturePointerTracker(ViewportControllerWPtr controllerW); + virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual bool IsAlive() const ORTHANC_OVERRIDE; + + protected: + ViewportControllerPtr GetController(); + + private: + ViewportControllerWPtr controllerW_; + bool alive_; + int currentTouchCount_; + }; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/PointerTypes.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,81 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> + +namespace OrthancStone +{ + class Scene2D; + typedef boost::shared_ptr<Scene2D> Scene2DPtr; + + typedef boost::weak_ptr<Scene2D> Scene2DWPtr; + + class MeasureTool; + typedef boost::shared_ptr<MeasureTool> + MeasureToolPtr; + typedef boost::weak_ptr<MeasureTool> + MeasureToolWPtr; + + class LineMeasureTool; + typedef boost::shared_ptr<LineMeasureTool> + LineMeasureToolPtr; + + class AngleMeasureTool; + typedef boost::shared_ptr<AngleMeasureTool> + AngleMeasureToolPtr; + + class IPointerTracker; + typedef boost::shared_ptr<IPointerTracker> + PointerTrackerPtr; + + class IFlexiblePointerTracker; + typedef boost::shared_ptr<IFlexiblePointerTracker> + FlexiblePointerTrackerPtr; + + typedef boost::shared_ptr<LineMeasureTool> + LineMeasureToolPtr; + + class CreateMeasureCommand; + typedef boost::shared_ptr<CreateMeasureCommand> + CreateMeasureCommandPtr; + + class CreateLineMeasureCommand; + typedef boost::shared_ptr<CreateLineMeasureCommand> + CreateLineMeasureCommandPtr; + + class CreateAngleMeasureCommand; + typedef boost::shared_ptr<CreateAngleMeasureCommand> + CreateAngleMeasureCommandPtr; + + + typedef boost::shared_ptr<Scene2D> Scene2DPtr; + + class TrackerCommand; + typedef boost::shared_ptr<TrackerCommand> TrackerCommandPtr; + + class ViewportController; + typedef boost::shared_ptr<ViewportController> ViewportControllerPtr; + typedef boost::weak_ptr<ViewportController> ViewportControllerWPtr; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,137 @@ +/** + * 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 "ViewportController.h" +#include "MeasureCommands.h" + +#include <Framework/StoneException.h> + +#include <boost/make_shared.hpp> + +using namespace Orthanc; + +namespace OrthancStone +{ + ViewportController::ViewportController(MessageBroker& broker) + : IObservable(broker) + , numAppliedCommands_(0) + { + scene_ = boost::make_shared<Scene2D>(); + } + + Scene2DPtr ViewportController::GetScene() + { + return scene_; + } + + bool ViewportController::HandlePointerEvent(PointerEvent e) + { + throw StoneException(ErrorCode_NotImplemented); + } + + std::vector<MeasureToolPtr> ViewportController::HitTestMeasureTools( + ScenePoint2D p) + { + std::vector<MeasureToolPtr> ret; + + + //for (size_t i = 0; i < measureTools_.size(); ++i) + //{ + + //} + return ret; + } + + const OrthancStone::AffineTransform2D& ViewportController::GetCanvasToSceneTransform() const + { + return scene_->GetCanvasToSceneTransform(); + } + + const OrthancStone::AffineTransform2D& ViewportController::GetSceneToCanvasTransform() const + { + return scene_->GetSceneToCanvasTransform(); + } + + void ViewportController::SetSceneToCanvasTransform( + const AffineTransform2D& transform) + { + scene_->SetSceneToCanvasTransform(transform); + BroadcastMessage(SceneTransformChanged(*this)); + } + + void ViewportController::FitContent( + unsigned int canvasWidth, unsigned int canvasHeight) + { + scene_->FitContent(canvasWidth, canvasHeight); + BroadcastMessage(SceneTransformChanged(*this)); + } + + void ViewportController::PushCommand(TrackerCommandPtr command) + { + commandStack_.erase( + commandStack_.begin() + numAppliedCommands_, + commandStack_.end()); + + ORTHANC_ASSERT(std::find(commandStack_.begin(), commandStack_.end(), command) + == commandStack_.end(), "Duplicate command"); + commandStack_.push_back(command); + numAppliedCommands_++; + } + + void ViewportController::Undo() + { + ORTHANC_ASSERT(CanUndo(), ""); + commandStack_[numAppliedCommands_-1]->Undo(); + numAppliedCommands_--; + } + + void ViewportController::Redo() + { + ORTHANC_ASSERT(CanRedo(), ""); + commandStack_[numAppliedCommands_]->Redo(); + numAppliedCommands_++; + } + + bool ViewportController::CanUndo() const + { + return numAppliedCommands_ > 0; + } + + bool ViewportController::CanRedo() const + { + return numAppliedCommands_ < commandStack_.size(); + } + + void ViewportController::AddMeasureTool(MeasureToolPtr measureTool) + { + ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool) + == measureTools_.end(), "Duplicate measure tool"); + measureTools_.push_back(measureTool); + } + + void ViewportController::RemoveMeasureTool(MeasureToolPtr measureTool) + { + ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool) + != measureTools_.end(), "Measure tool not found"); + measureTools_.push_back(measureTool); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,136 @@ +/** + * 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 "PointerTypes.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/PointerEvent.h> +#include <Framework/Scene2DViewport/IFlexiblePointerTracker.h> + +#include <stack> + +namespace OrthancStone +{ + /** + This object is responsible for hosting a scene, responding to messages from + the model and updating the scene accordingly. + + It contains the list of active measuring tools as well as the stack + where measuring tool commands are stored. + + The active tracker is also stored in the viewport controller. + + Each canvas or other GUI area where we want to display a 2D image, either + directly or through slicing must be assigned a ViewportController. + */ + class ViewportController : public IObservable + { + public: + ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, \ + SceneTransformChanged, ViewportController); + + ViewportController(MessageBroker& broker); + + Scene2DPtr GetScene(); + + /** + This method is called by the GUI system and should update/delete the + current tracker + */ + bool HandlePointerEvent(PointerEvent e); + + /** + This method returns the list of measure tools containing the supplied point + (in scene coords). A tracker can then be requested from the chosen + measure tool, if needed + */ + std::vector<MeasureToolPtr> HitTestMeasureTools(ScenePoint2D p); + + /** + With this method, the object takes ownership of the supplied tracker and + updates it according to user interaction + */ + void SetActiveTracker(FlexiblePointerTrackerPtr tracker); + + /** Forwarded to the underlying scene */ + const AffineTransform2D& GetCanvasToSceneTransform() const; + + /** Forwarded to the underlying scene */ + const AffineTransform2D& GetSceneToCanvasTransform() const; + + /** Forwarded to the underlying scene, and broadcasted to the observers */ + void SetSceneToCanvasTransform(const AffineTransform2D& transform); + + /** Forwarded to the underlying scene, and broadcasted to the observers */ + void FitContent(unsigned int canvasWidth, unsigned int canvasHeight); + + /** + Stores a command : + - this first trims the undo stack to keep the first numAppliedCommands_ + - then it adds the supplied command at the top of the undo stack + + In other words, when a new command is pushed, all the undone (and not + redone) commands are removed. + */ + void PushCommand(TrackerCommandPtr command); + + /** + Undoes the command at the top of the undo stack, or throws if there is no + command to undo. + You can check "CanUndo" first to protect against extraneous redo. + */ + void Undo(); + + /** + Redoes the command that is just above the last applied command in the undo + stack or throws if there is no command to redo. + You can check "CanRedo" first to protect against extraneous redo. + */ + void Redo(); + + /** selfexpl */ + bool CanUndo() const; + + /** selfexpl */ + bool CanRedo() const; + + /** Adds a new measure tool */ + void AddMeasureTool(MeasureToolPtr measureTool); + + /** Removes a measure tool or throws if it cannot be found */ + void RemoveMeasureTool(MeasureToolPtr measureTool); + + private: + std::vector<TrackerCommandPtr> commandStack_; + + /** + This is always between >= 0 and <= undoStack_.size() and gives the + position where the controller is in the undo stack. + - If numAppliedCommands_ > 0, one can undo + - If numAppliedCommands_ < numAppliedCommands_.size(), one can redo + */ + size_t numAppliedCommands_; + std::vector<MeasureToolPtr> measureTools_; + Scene2DPtr scene_; + FlexiblePointerTrackerPtr tracker_; + }; +}
--- a/Framework/SmartLoader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/SmartLoader.cpp Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ #include "Framework/Layers/FrameRenderer.h" #include "Core/Logging.h" -namespace OrthancStone +namespace Deprecated { enum CachedSliceStatus { @@ -53,8 +53,8 @@ virtual ILayerRenderer* CreateRenderer() const { - bool isFull = (that_.effectiveQuality_ == SliceImageQuality_FullPng || - that_.effectiveQuality_ == SliceImageQuality_FullPam); + bool isFull = (that_.effectiveQuality_ == OrthancStone::SliceImageQuality_FullPng || + that_.effectiveQuality_ == OrthancStone::SliceImageQuality_FullPam); return FrameRenderer::CreateRenderer(*that_.image_, *that_.slice_, isFull); } @@ -63,11 +63,11 @@ unsigned int sliceIndex_; std::auto_ptr<Slice> slice_; boost::shared_ptr<Orthanc::ImageAccessor> image_; - SliceImageQuality effectiveQuality_; + OrthancStone::SliceImageQuality effectiveQuality_; CachedSliceStatus status_; public: - CachedSlice(MessageBroker& broker) : + CachedSlice(OrthancStone::MessageBroker& broker) : IVolumeSlicer(broker) { } @@ -76,15 +76,15 @@ { } - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice) + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice) { // TODO: viewportSlice is not used !!!! slice_->GetExtent(points); return true; } - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) { // TODO: viewportSlice is not used !!!! @@ -118,11 +118,11 @@ }; - SmartLoader::SmartLoader(MessageBroker& broker, + SmartLoader::SmartLoader(OrthancStone::MessageBroker& broker, OrthancApiClient& orthancApiClient) : IObservable(broker), IObserver(broker), - imageQuality_(SliceImageQuality_FullPam), + imageQuality_(OrthancStone::SliceImageQuality_FullPam), orthancApiClient_(orthancApiClient) { } @@ -152,9 +152,9 @@ { layerSource.reset(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_)); dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); } @@ -169,7 +169,7 @@ } else { - throw StoneException(ErrorCode_CanOnlyAddOneLayerAtATime); + throw OrthancStone::StoneException(OrthancStone::ErrorCode_CanOnlyAddOneLayerAtATime); } if (cachedSlice != NULL) @@ -201,9 +201,9 @@ std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_)); dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); - layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); + layerSource->RegisterObserverCallback(new OrthancStone::Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); // keep a ref to the VolumeSlicer until the slice is fully loaded and saved to cache
--- a/Framework/SmartLoader.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/SmartLoader.h Tue May 21 13:25:58 2019 +0200 @@ -26,11 +26,11 @@ #include "Messages/IObservable.h" #include "Toolbox/OrthancApiClient.h" -namespace OrthancStone +namespace Deprecated { class SliceViewerWidget; - class SmartLoader : public IObservable, public IObserver + class SmartLoader : public OrthancStone::IObservable, public OrthancStone::IObserver { class CachedSlice; @@ -41,17 +41,17 @@ typedef std::map<std::string, boost::shared_ptr<IVolumeSlicer> > PreloadingInstances; PreloadingInstances preloadingInstances_; - SliceImageQuality imageQuality_; + OrthancStone::SliceImageQuality imageQuality_; OrthancApiClient& orthancApiClient_; public: - SmartLoader(MessageBroker& broker, OrthancApiClient& orthancApiClient); // TODO: add maxPreloadStorageSizeInBytes + SmartLoader(OrthancStone::MessageBroker& broker, OrthancApiClient& orthancApiClient); // TODO: add maxPreloadStorageSizeInBytes // void PreloadStudy(const std::string studyId); // void PreloadSeries(const std::string seriesId); void PreloadSlice(const std::string instanceId, unsigned int frame); - void SetImageQuality(SliceImageQuality imageQuality) { imageQuality_ = imageQuality; } + void SetImageQuality(OrthancStone::SliceImageQuality imageQuality) { imageQuality_ = imageQuality; } void SetFrameInWidget(SliceViewerWidget& sliceViewer, size_t layerIndex, const std::string& instanceId, unsigned int frame);
--- a/Framework/StoneException.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/StoneException.h Tue May 21 13:25:58 2019 +0200 @@ -113,3 +113,13 @@ } +// See https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-multi-stmts +// (or google "Multiple lines macro C++ faq lite" if link is dead) +#define ORTHANC_ASSERT(cond,streamChainMessage) \ + if (!(cond)) { \ + std::stringstream sst; \ + sst << "Assertion failed. Condition = \"" #cond "\" Message = \"" << streamChainMessage << "\""; \ + std::string sstr = sst.str(); \ + throw OrthancException(ErrorCode_InternalError,sstr.c_str()); \ + } else (void)0 +
--- a/Framework/Toolbox/BaseWebService.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/BaseWebService.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,20 +26,20 @@ #include "Platforms/Generic/IOracleCommand.h" #include <boost/shared_ptr.hpp> -namespace OrthancStone +namespace Deprecated { class BaseWebService::BaseWebServicePayload : public Orthanc::IDynamicObject { private: - std::auto_ptr< MessageHandler<IWebService::HttpRequestSuccessMessage> > userSuccessHandler_; - std::auto_ptr< MessageHandler<IWebService::HttpRequestErrorMessage> > userFailureHandler_; + std::auto_ptr< OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> > userSuccessHandler_; + std::auto_ptr< OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> > userFailureHandler_; std::auto_ptr< Orthanc::IDynamicObject> userPayload_; public: - BaseWebServicePayload(MessageHandler<IWebService::HttpRequestSuccessMessage>* userSuccessHandler, - MessageHandler<IWebService::HttpRequestErrorMessage>* userFailureHandler, + BaseWebServicePayload(OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* userSuccessHandler, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* userFailureHandler, Orthanc::IDynamicObject* userPayload) : userSuccessHandler_(userSuccessHandler), userFailureHandler_(userFailureHandler), @@ -83,17 +83,17 @@ void BaseWebService::GetAsync(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, unsigned int timeoutInSeconds) { if (cache_.find(uri) == cache_.end()) { GetAsyncInternal(uri, headers, new BaseWebService::BaseWebServicePayload(successCallback, failureCallback, payload), // ownership is transfered - new Callable<BaseWebService, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestSuccessMessage> (*this, &BaseWebService::CacheAndNotifyHttpSuccess), - new Callable<BaseWebService, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<BaseWebService, IWebService::HttpRequestErrorMessage> (*this, &BaseWebService::NotifyHttpError), timeoutInSeconds); }
--- a/Framework/Toolbox/BaseWebService.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/BaseWebService.h Tue May 21 13:25:58 2019 +0200 @@ -26,11 +26,11 @@ #include <string> #include <map> -namespace OrthancStone +namespace Deprecated { // This is an intermediate of IWebService that implements some caching on // the HTTP GET requests - class BaseWebService : public IWebService, public IObserver + class BaseWebService : public IWebService, public OrthancStone::IObserver { public: class CachedHttpRequestSuccessMessage @@ -85,7 +85,7 @@ public: - BaseWebService(MessageBroker& broker) : + BaseWebService(OrthancStone::MessageBroker& broker) : IWebService(broker), IObserver(broker), cacheEnabled_(true) @@ -104,21 +104,21 @@ virtual void GetAsync(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60); protected: virtual void GetAsyncInternal(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) = 0; + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) = 0; private: void NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message);
--- a/Framework/Toolbox/DicomFrameConverter.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/DicomFrameConverter.cpp Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ #include <Core/OrthancException.h> #include <Core/Toolbox.h> -namespace OrthancStone +namespace Deprecated { static const Orthanc::DicomTag IMAGE_TAGS[] = { @@ -61,9 +61,9 @@ { SetDefaultParameters(); - Vector c, w; - if (LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && - LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && + OrthancStone::Vector c, w; + if (OrthancStone::LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && + OrthancStone::LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && c.size() > 0 && w.size() > 0) {
--- a/Framework/Toolbox/DicomFrameConverter.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/DicomFrameConverter.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ #include <memory> -namespace OrthancStone +namespace Deprecated { /** * This class is responsible for converting the pixel format of a
--- a/Framework/Toolbox/DownloadStack.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/DownloadStack.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <cassert> -namespace OrthancStone +namespace Deprecated { bool DownloadStack::CheckInvariants() const { @@ -77,8 +77,8 @@ { for (size_t i = 0; i < size; i++) { - nodes_[i].prev_ = i - 1; - nodes_[i].next_ = i + 1; + nodes_[i].prev_ = static_cast<int>(i - 1); + nodes_[i].next_ = static_cast<int>(i + 1); nodes_[i].dequeued_ = false; }
--- a/Framework/Toolbox/DownloadStack.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/DownloadStack.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <vector> #include <boost/noncopyable.hpp> -namespace OrthancStone +namespace Deprecated { class DownloadStack : public boost::noncopyable {
--- a/Framework/Toolbox/FiniteProjectiveCamera.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/FiniteProjectiveCamera.cpp Tue May 21 13:25:58 2019 +0200 @@ -316,7 +316,7 @@ LOG(WARNING) << "Output pixel format: " << Orthanc::EnumerationToString(target.GetFormat()); std::auto_ptr<OrthancStone::ParallelSlices> slices(source.GetGeometry(projection)); - const OrthancStone::Vector pixelSpacing = source.GetVoxelDimensions(projection); + const OrthancStone::Vector pixelSpacing = source.GetGeometry().GetVoxelDimensions(projection); const unsigned int targetWidth = target.GetWidth(); const unsigned int targetHeight = target.GetHeight(); @@ -360,7 +360,8 @@ // Read and accumulate the value of the pixel float pixel; - if (pixelReader.GetFloatValue(pixel, ix, iy)) + if (pixelReader.GetFloatValue( + pixel, static_cast<float>(ix), static_cast<float>(iy))) { if (MIP) {
--- a/Framework/Toolbox/IDelayedCallExecutor.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/IDelayedCallExecutor.h Tue May 21 13:25:58 2019 +0200 @@ -30,18 +30,18 @@ #include <string> #include <map> -namespace OrthancStone +namespace Deprecated { // The IDelayedCall executes a callback after a delay (equivalent to timeout() function in javascript). class IDelayedCallExecutor : public boost::noncopyable { protected: - MessageBroker& broker_; + OrthancStone::MessageBroker& broker_; public: ORTHANC_STONE_DEFINE_EMPTY_MESSAGE(__FILE__, __LINE__, TimeoutMessage); - IDelayedCallExecutor(MessageBroker& broker) : + IDelayedCallExecutor(OrthancStone::MessageBroker& broker) : broker_(broker) { } @@ -52,7 +52,7 @@ } - virtual void Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, - unsigned int timeoutInMs = 1000) = 0; + virtual void Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, + unsigned int timeoutInMs = 1000) = 0; }; }
--- a/Framework/Toolbox/IWebService.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/IWebService.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { const Orthanc::IDynamicObject& IWebService::HttpRequestSuccessMessage::GetPayload() const
--- a/Framework/Toolbox/IWebService.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/IWebService.h Tue May 21 13:25:58 2019 +0200 @@ -30,7 +30,7 @@ #include <string> #include <map> -namespace OrthancStone +namespace Deprecated { // The IWebService performs HTTP requests. // Since applications can run in native or WASM environment and, since @@ -40,12 +40,12 @@ class IWebService : public boost::noncopyable { protected: - MessageBroker& broker_; + OrthancStone::MessageBroker& broker_; public: typedef std::map<std::string, std::string> HttpHeaders; - class HttpRequestSuccessMessage : public IMessage + class HttpRequestSuccessMessage : public OrthancStone::IMessage { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -99,7 +99,7 @@ }; - class HttpRequestErrorMessage : public IMessage + class HttpRequestErrorMessage : public OrthancStone::IMessage { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -129,7 +129,7 @@ }; - IWebService(MessageBroker& broker) : + IWebService(OrthancStone::MessageBroker& broker) : broker_(broker) { } @@ -144,23 +144,23 @@ virtual void GetAsync(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; virtual void PostAsync(const std::string& uri, const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; virtual void DeleteAsync(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; }; }
--- a/Framework/Toolbox/OrientedBoundingBox.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/OrientedBoundingBox.cpp Tue May 21 13:25:58 2019 +0200 @@ -37,8 +37,8 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); } - const CoordinateSystem3D& geometry = image.GetAxialGeometry(); - Vector dim = image.GetVoxelDimensions(VolumeProjection_Axial); + const CoordinateSystem3D& geometry = image.GetGeometry().GetAxialGeometry(); + Vector dim = image.GetGeometry().GetVoxelDimensions(VolumeProjection_Axial); u_ = geometry.GetAxisX(); v_ = geometry.GetAxisY();
--- a/Framework/Toolbox/OrthancApiClient.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/OrthancApiClient.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { const Orthanc::IDynamicObject& OrthancApiClient::JsonResponseReadyMessage::GetPayload() const { @@ -69,10 +69,10 @@ class OrthancApiClient::WebServicePayload : public Orthanc::IDynamicObject { private: - std::auto_ptr< MessageHandler<EmptyResponseReadyMessage> > emptyHandler_; - std::auto_ptr< MessageHandler<JsonResponseReadyMessage> > jsonHandler_; - std::auto_ptr< MessageHandler<BinaryResponseReadyMessage> > binaryHandler_; - std::auto_ptr< MessageHandler<IWebService::HttpRequestErrorMessage> > failureHandler_; + std::auto_ptr< OrthancStone::MessageHandler<EmptyResponseReadyMessage> > emptyHandler_; + std::auto_ptr< OrthancStone::MessageHandler<JsonResponseReadyMessage> > jsonHandler_; + std::auto_ptr< OrthancStone::MessageHandler<BinaryResponseReadyMessage> > binaryHandler_; + std::auto_ptr< OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> > failureHandler_; std::auto_ptr< Orthanc::IDynamicObject > userPayload_; void NotifyConversionError(const IWebService::HttpRequestSuccessMessage& message) const @@ -85,8 +85,8 @@ } public: - WebServicePayload(MessageHandler<EmptyResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, + WebServicePayload(OrthancStone::MessageHandler<EmptyResponseReadyMessage>* handler, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, Orthanc::IDynamicObject* userPayload) : emptyHandler_(handler), failureHandler_(failureHandler), @@ -98,8 +98,8 @@ } } - WebServicePayload(MessageHandler<BinaryResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, + WebServicePayload(OrthancStone::MessageHandler<BinaryResponseReadyMessage>* handler, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, Orthanc::IDynamicObject* userPayload) : binaryHandler_(handler), failureHandler_(failureHandler), @@ -111,8 +111,8 @@ } } - WebServicePayload(MessageHandler<JsonResponseReadyMessage>* handler, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, + WebServicePayload(OrthancStone::MessageHandler<JsonResponseReadyMessage>* handler, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureHandler, Orthanc::IDynamicObject* userPayload) : jsonHandler_(handler), failureHandler_(failureHandler), @@ -140,7 +140,7 @@ else if (jsonHandler_.get() != NULL) { Json::Value response; - if (MessagingToolbox::ParseJson(response, message.GetAnswer(), message.GetAnswerSize())) + if (OrthancStone::MessagingToolbox::ParseJson(response, message.GetAnswer(), message.GetAnswerSize())) { jsonHandler_->Apply(OrthancApiClient::JsonResponseReadyMessage (message.GetUri(), response, userPayload_.get())); @@ -167,7 +167,7 @@ }; - OrthancApiClient::OrthancApiClient(MessageBroker& broker, + OrthancApiClient::OrthancApiClient(OrthancStone::MessageBroker& broker, IWebService& web, const std::string& baseUrl) : IObservable(broker), @@ -180,17 +180,17 @@ void OrthancApiClient::GetJsonAsync( const std::string& uri, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { IWebService::HttpHeaders emptyHeaders; web_.GetAsync(baseUrl_ + uri, emptyHeaders, new WebServicePayload(successCallback, failureCallback, payload), - new Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> (*this, &OrthancApiClient::NotifyHttpError)); } @@ -198,8 +198,8 @@ void OrthancApiClient::GetBinaryAsync( const std::string& uri, const std::string& contentType, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<BinaryResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { IWebService::HttpHeaders headers; @@ -210,17 +210,17 @@ void OrthancApiClient::GetBinaryAsync( const std::string& uri, const IWebService::HttpHeaders& headers, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<BinaryResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { // printf("GET [%s] [%s]\n", baseUrl_.c_str(), uri.c_str()); web_.GetAsync(baseUrl_ + uri, headers, new WebServicePayload(successCallback, failureCallback, payload), - new Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> (*this, &OrthancApiClient::NotifyHttpError)); } @@ -228,15 +228,15 @@ void OrthancApiClient::PostBinaryAsyncExpectJson( const std::string& uri, const std::string& body, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, new WebServicePayload(successCallback, failureCallback, payload), - new Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> (*this, &OrthancApiClient::NotifyHttpError)); } @@ -251,27 +251,27 @@ void OrthancApiClient::PostBinaryAsync( const std::string& uri, const std::string& body, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload /* takes ownership */) { web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, new WebServicePayload(successCallback, failureCallback, payload), - new Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> (*this, &OrthancApiClient::NotifyHttpError)); } void OrthancApiClient::PostJsonAsyncExpectJson( const std::string& uri, const Json::Value& data, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { std::string body; - MessagingToolbox::JsonToString(body, data); + OrthancStone::MessagingToolbox::JsonToString(body, data); return PostBinaryAsyncExpectJson(uri, body, successCallback, failureCallback, payload); } @@ -280,33 +280,33 @@ const Json::Value& data) { std::string body; - MessagingToolbox::JsonToString(body, data); + OrthancStone::MessagingToolbox::JsonToString(body, data); return PostBinaryAsync(uri, body); } void OrthancApiClient::PostJsonAsync( const std::string& uri, const Json::Value& data, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload /* takes ownership */) { std::string body; - MessagingToolbox::JsonToString(body, data); + OrthancStone::MessagingToolbox::JsonToString(body, data); return PostBinaryAsync(uri, body, successCallback, failureCallback, payload); } void OrthancApiClient::DeleteAsync( const std::string& uri, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, Orthanc::IDynamicObject* payload) { web_.DeleteAsync(baseUrl_ + uri, IWebService::HttpHeaders(), new WebServicePayload(successCallback, failureCallback, payload), - new Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestSuccessMessage> (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> + new OrthancStone::Callable<OrthancApiClient, IWebService::HttpRequestErrorMessage> (*this, &OrthancApiClient::NotifyHttpError)); }
--- a/Framework/Toolbox/OrthancApiClient.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/OrthancApiClient.h Tue May 21 13:25:58 2019 +0200 @@ -28,14 +28,14 @@ #include "../Messages/IObservable.h" #include "../Messages/Promise.h" -namespace OrthancStone +namespace Deprecated { class OrthancApiClient : - public IObservable, - public IObserver + public OrthancStone::IObservable, + public OrthancStone::IObserver { public: - class JsonResponseReadyMessage : public IMessage + class JsonResponseReadyMessage : public OrthancStone::IMessage { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -73,7 +73,7 @@ }; - class BinaryResponseReadyMessage : public IMessage + class BinaryResponseReadyMessage : public OrthancStone::IMessage { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -119,7 +119,7 @@ }; - class EmptyResponseReadyMessage : public IMessage + class EmptyResponseReadyMessage : public OrthancStone::IMessage { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -158,7 +158,7 @@ std::string baseUrl_; public: - OrthancApiClient(MessageBroker& broker, + OrthancApiClient(OrthancStone::MessageBroker& broker, IWebService& web, const std::string& baseUrl); @@ -170,36 +170,36 @@ // schedule a GET request expecting a JSON response. void GetJsonAsync(const std::string& uri, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a GET request expecting a binary response. void GetBinaryAsync(const std::string& uri, const std::string& contentType, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<BinaryResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a GET request expecting a binary response. void GetBinaryAsync(const std::string& uri, const IWebService::HttpHeaders& headers, - MessageHandler<BinaryResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<BinaryResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a POST request expecting a JSON response. void PostBinaryAsyncExpectJson(const std::string& uri, const std::string& body, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a POST request expecting a JSON response. void PostJsonAsyncExpectJson(const std::string& uri, const Json::Value& data, - MessageHandler<JsonResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<JsonResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a POST request and don't mind the response. @@ -209,8 +209,8 @@ // schedule a POST request and don't expect any response. void PostJsonAsync(const std::string& uri, const Json::Value& data, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); @@ -221,14 +221,14 @@ // schedule a POST request and don't expect any response. void PostBinaryAsync(const std::string& uri, const std::string& body, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); // schedule a DELETE request expecting an empty response. void DeleteAsync(const std::string& uri, - MessageHandler<EmptyResponseReadyMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<EmptyResponseReadyMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); void NotifyHttpSuccess(const IWebService::HttpRequestSuccessMessage& message);
--- a/Framework/Toolbox/OrthancSlicesLoader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/OrthancSlicesLoader.cpp Tue May 21 13:25:58 2019 +0200 @@ -68,7 +68,7 @@ -namespace OrthancStone +namespace Deprecated { class OrthancSlicesLoader::Operation : public Orthanc::IDynamicObject { @@ -78,7 +78,7 @@ unsigned int sliceIndex_; const Slice* slice_; std::string instanceId_; - SliceImageQuality quality_; + OrthancStone::SliceImageQuality quality_; Operation(Mode mode) : mode_(mode) @@ -91,7 +91,7 @@ return mode_; } - SliceImageQuality GetQuality() const + OrthancStone::SliceImageQuality GetQuality() const { assert(mode_ == Mode_LoadImage || mode_ == Mode_LoadRawImage); @@ -144,7 +144,7 @@ static Operation* DownloadSliceImage(unsigned int sliceIndex, const Slice& slice, - SliceImageQuality quality) + OrthancStone::SliceImageQuality quality) { std::auto_ptr<Operation> tmp(new Operation(Mode_LoadImage)); tmp->sliceIndex_ = sliceIndex; @@ -159,7 +159,7 @@ std::auto_ptr<Operation> tmp(new Operation(Mode_LoadRawImage)); tmp->sliceIndex_ = sliceIndex; tmp->slice_ = &slice; - tmp->quality_ = SliceImageQuality_InternalRaw; + tmp->quality_ = OrthancStone::SliceImageQuality_InternalRaw; return tmp.release(); } @@ -231,7 +231,7 @@ OrthancPlugins::FullOrthancDataset dataset(series[instances[i]]); Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); + OrthancStone::MessagingToolbox::ConvertDataset(dicom, dataset); unsigned int frames; if (!dicom.ParseUnsignedInteger32(frames, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES)) @@ -244,7 +244,7 @@ std::auto_ptr<Slice> slice(new Slice); if (slice->ParseOrthancFrame(dicom, instances[i], frame)) { - CoordinateSystem3D geometry = slice->GetGeometry(); + OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); slices_.AddSlice(geometry, slice.release()); } else @@ -265,7 +265,7 @@ OrthancPlugins::FullOrthancDataset dataset(tags); Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); + OrthancStone::MessagingToolbox::ConvertDataset(dicom, dataset); unsigned int frames; if (!dicom.ParseUnsignedInteger32(frames, Orthanc::DICOM_TAG_NUMBER_OF_FRAMES)) @@ -280,7 +280,7 @@ std::auto_ptr<Slice> slice(new Slice); if (slice->ParseOrthancFrame(dicom, instanceId, frame)) { - CoordinateSystem3D geometry = slice->GetGeometry(); + OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); slices_.AddSlice(geometry, slice.release()); } else @@ -306,14 +306,14 @@ state_ = State_GeometryReady; Orthanc::DicomMap dicom; - MessagingToolbox::ConvertDataset(dicom, dataset); + OrthancStone::MessagingToolbox::ConvertDataset(dicom, dataset); std::auto_ptr<Slice> slice(new Slice); if (slice->ParseOrthancFrame(dicom, instanceId, frame)) { LOG(INFO) << "Loaded instance geometry " << instanceId; - CoordinateSystem3D geometry = slice->GetGeometry(); + OrthancStone::CoordinateSystem3D geometry = slice->GetGeometry(); slices_.AddSlice(geometry, slice.release()); BroadcastMessage(SliceGeometryReadyMessage(*this)); @@ -544,7 +544,7 @@ float scaling = static_cast<float>(stretchHigh - stretchLow) / 255.0f; - if (!LinearAlgebra::IsCloseToZero(scaling)) + if (!OrthancStone::LinearAlgebra::IsCloseToZero(scaling)) { float offset = static_cast<float>(stretchLow) / scaling; Orthanc::ImageProcessing::ShiftScale(*image, offset, scaling, true); @@ -639,10 +639,10 @@ } - OrthancSlicesLoader::OrthancSlicesLoader(MessageBroker& broker, + OrthancSlicesLoader::OrthancSlicesLoader(OrthancStone::MessageBroker& broker, OrthancApiClient& orthanc) : - IObservable(broker), - IObserver(broker), + OrthancStone::IObservable(broker), + OrthancStone::IObserver(broker), orthanc_(orthanc), state_(State_Initialization) { @@ -659,8 +659,8 @@ { state_ = State_LoadingGeometry; orthanc_.GetJsonAsync("/series/" + seriesId + "/instances-tags", - new Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSeriesGeometry), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), + new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSeriesGeometry), + new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), NULL); } } @@ -678,8 +678,8 @@ // Tag "3004-000c" is "Grid Frame Offset Vector", which is // mandatory to read RT DOSE, but is too long to be returned by default orthanc_.GetJsonAsync("/instances/" + instanceId + "/tags?ignore-length=3004-000c", - new Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseInstanceGeometry), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), + new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseInstanceGeometry), + new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), Operation::DownloadInstanceGeometry(instanceId)); } } @@ -697,8 +697,8 @@ state_ = State_LoadingGeometry; orthanc_.GetJsonAsync("/instances/" + instanceId + "/tags", - new Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseFrameGeometry), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), + new OrthancStone::Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseFrameGeometry), + new OrthancStone::Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnGeometryError), Operation::DownloadFrameGeometry(instanceId, frame)); } } @@ -733,7 +733,7 @@ bool OrthancSlicesLoader::LookupSlice(size_t& index, - const CoordinateSystem3D& plane) const + const OrthancStone::CoordinateSystem3D& plane) const { if (state_ != State_GeometryReady) { @@ -771,16 +771,22 @@ } orthanc_.GetBinaryAsync(uri, "image/png", - new Callable<OrthancSlicesLoader, OrthancApiClient::BinaryResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSliceImagePng), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage(index, slice, SliceImageQuality_FullPng)); - } + new OrthancStone::Callable<OrthancSlicesLoader, + OrthancApiClient::BinaryResponseReadyMessage> + (*this, &OrthancSlicesLoader::ParseSliceImagePng), + new OrthancStone::Callable<OrthancSlicesLoader, + IWebService::HttpRequestErrorMessage> + (*this, &OrthancSlicesLoader::OnSliceImageError), + Operation::DownloadSliceImage( + static_cast<unsigned int>(index), slice, OrthancStone::SliceImageQuality_FullPng)); +} void OrthancSlicesLoader::ScheduleSliceImagePam(const Slice& slice, size_t index) { - std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + - boost::lexical_cast<std::string>(slice.GetFrame())); + std::string uri = + ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + + boost::lexical_cast<std::string>(slice.GetFrame())); switch (slice.GetConverter().GetExpectedPixelFormat()) { @@ -801,30 +807,35 @@ } orthanc_.GetBinaryAsync(uri, "image/x-portable-arbitrarymap", - new Callable<OrthancSlicesLoader, OrthancApiClient::BinaryResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSliceImagePam), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage(index, slice, SliceImageQuality_FullPam)); + new OrthancStone::Callable<OrthancSlicesLoader, + OrthancApiClient::BinaryResponseReadyMessage> + (*this, &OrthancSlicesLoader::ParseSliceImagePam), + new OrthancStone::Callable<OrthancSlicesLoader, + IWebService::HttpRequestErrorMessage> + (*this, &OrthancSlicesLoader::OnSliceImageError), + Operation::DownloadSliceImage(static_cast<unsigned int>(index), + slice, OrthancStone::SliceImageQuality_FullPam)); } void OrthancSlicesLoader::ScheduleSliceImageJpeg(const Slice& slice, size_t index, - SliceImageQuality quality) + OrthancStone::SliceImageQuality quality) { unsigned int value; switch (quality) { - case SliceImageQuality_Jpeg50: + case OrthancStone::SliceImageQuality_Jpeg50: value = 50; break; - case SliceImageQuality_Jpeg90: + case OrthancStone::SliceImageQuality_Jpeg90: value = 90; break; - case SliceImageQuality_Jpeg95: + case OrthancStone::SliceImageQuality_Jpeg95: value = 95; break; @@ -839,15 +850,20 @@ boost::lexical_cast<std::string>(slice.GetFrame())); orthanc_.GetJsonAsync(uri, - new Callable<OrthancSlicesLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSliceImageJpeg), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceImage(index, slice, quality)); + new OrthancStone::Callable<OrthancSlicesLoader, + OrthancApiClient::JsonResponseReadyMessage> + (*this, &OrthancSlicesLoader::ParseSliceImageJpeg), + new OrthancStone::Callable<OrthancSlicesLoader, + IWebService::HttpRequestErrorMessage> + (*this, &OrthancSlicesLoader::OnSliceImageError), + Operation::DownloadSliceImage( + static_cast<unsigned int>(index), slice, quality)); } void OrthancSlicesLoader::ScheduleLoadSliceImage(size_t index, - SliceImageQuality quality) + OrthancStone::SliceImageQuality quality) { if (state_ != State_GeometryReady) { @@ -860,10 +876,10 @@ { switch (quality) { - case SliceImageQuality_FullPng: + case OrthancStone::SliceImageQuality_FullPng: ScheduleSliceImagePng(slice, index); break; - case SliceImageQuality_FullPam: + case OrthancStone::SliceImageQuality_FullPam: ScheduleSliceImagePam(slice, index); break; default: @@ -875,9 +891,14 @@ std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + boost::lexical_cast<std::string>(slice.GetFrame()) + "/raw.gz"); orthanc_.GetBinaryAsync(uri, IWebService::HttpHeaders(), - new Callable<OrthancSlicesLoader, OrthancApiClient::BinaryResponseReadyMessage>(*this, &OrthancSlicesLoader::ParseSliceRawImage), - new Callable<OrthancSlicesLoader, IWebService::HttpRequestErrorMessage>(*this, &OrthancSlicesLoader::OnSliceImageError), - Operation::DownloadSliceRawImage(index, slice)); + new OrthancStone::Callable<OrthancSlicesLoader, + OrthancApiClient::BinaryResponseReadyMessage> + (*this, &OrthancSlicesLoader::ParseSliceRawImage), + new OrthancStone::Callable<OrthancSlicesLoader, + IWebService::HttpRequestErrorMessage> + (*this, &OrthancSlicesLoader::OnSliceImageError), + Operation::DownloadSliceRawImage( + static_cast<unsigned int>(index), slice)); } } }
--- a/Framework/Toolbox/OrthancSlicesLoader.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/OrthancSlicesLoader.h Tue May 21 13:25:58 2019 +0200 @@ -31,16 +31,16 @@ #include <Core/Images/Image.h> -namespace OrthancStone +namespace Deprecated { - class OrthancSlicesLoader : public IObservable, public IObserver + class OrthancSlicesLoader : public OrthancStone::IObservable, public OrthancStone::IObserver { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SliceGeometryReadyMessage, OrthancSlicesLoader); ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SliceGeometryErrorMessage, OrthancSlicesLoader); - class SliceImageReadyMessage : public OriginMessage<OrthancSlicesLoader> + class SliceImageReadyMessage : public OrthancStone::OriginMessage<OrthancSlicesLoader> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -48,14 +48,14 @@ unsigned int sliceIndex_; const Slice& slice_; const Orthanc::ImageAccessor& image_; - SliceImageQuality effectiveQuality_; + OrthancStone::SliceImageQuality effectiveQuality_; public: SliceImageReadyMessage(const OrthancSlicesLoader& origin, unsigned int sliceIndex, const Slice& slice, const Orthanc::ImageAccessor& image, - SliceImageQuality effectiveQuality) : + OrthancStone::SliceImageQuality effectiveQuality) : OriginMessage(origin), sliceIndex_(sliceIndex), slice_(slice), @@ -79,27 +79,27 @@ return image_; } - SliceImageQuality GetEffectiveQuality() const + OrthancStone::SliceImageQuality GetEffectiveQuality() const { return effectiveQuality_; } }; - class SliceImageErrorMessage : public OriginMessage<OrthancSlicesLoader> + class SliceImageErrorMessage : public OrthancStone::OriginMessage<OrthancSlicesLoader> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); private: const Slice& slice_; unsigned int sliceIndex_; - SliceImageQuality effectiveQuality_; + OrthancStone::SliceImageQuality effectiveQuality_; public: SliceImageErrorMessage(const OrthancSlicesLoader& origin, unsigned int sliceIndex, const Slice& slice, - SliceImageQuality effectiveQuality) : + OrthancStone::SliceImageQuality effectiveQuality) : OriginMessage(origin), slice_(slice), sliceIndex_(sliceIndex), @@ -116,7 +116,7 @@ return slice_; } - SliceImageQuality GetEffectiveQuality() const + OrthancStone::SliceImageQuality GetEffectiveQuality() const { return effectiveQuality_; } @@ -145,7 +145,7 @@ OrthancApiClient& orthanc_; State state_; - SlicesSorter slices_; + OrthancStone::SlicesSorter slices_; void NotifySliceImageSuccess(const Operation& operation, const Orthanc::ImageAccessor& image); @@ -178,12 +178,12 @@ void ScheduleSliceImageJpeg(const Slice& slice, size_t index, - SliceImageQuality quality); + OrthancStone::SliceImageQuality quality); void SortAndFinalizeSlices(); public: - OrthancSlicesLoader(MessageBroker& broker, + OrthancSlicesLoader(OrthancStone::MessageBroker& broker, //ISliceLoaderObserver& callback, OrthancApiClient& orthancApi); @@ -201,9 +201,9 @@ const Slice& GetSlice(size_t index) const; bool LookupSlice(size_t& index, - const CoordinateSystem3D& plane) const; + const OrthancStone::CoordinateSystem3D& plane) const; void ScheduleLoadSliceImage(size_t index, - SliceImageQuality requestedQuality); + OrthancStone::SliceImageQuality requestedQuality); }; }
--- a/Framework/Toolbox/ParallelSlicesCursor.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/ParallelSlicesCursor.cpp Tue May 21 13:25:58 2019 +0200 @@ -110,7 +110,7 @@ return false; } - int count = slices_->GetSliceCount(); + int count = static_cast<int>(slices_->GetSliceCount()); if (count == 0) { return false; @@ -123,7 +123,7 @@ } else { - slice = currentSlice_; + slice = static_cast<int>(currentSlice_); } switch (mode)
--- a/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Tue May 21 13:25:58 2019 +0200 @@ -195,15 +195,20 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - intermediateWidth_ = std::ceil(extent.GetWidth() / maxScaling); - intermediateHeight_ = std::ceil(extent.GetHeight() / maxScaling); + intermediateWidth_ = + static_cast<unsigned int>(std::ceil(extent.GetWidth() / maxScaling)); + intermediateHeight_ = + static_cast<unsigned int>(std::ceil(extent.GetHeight() / maxScaling)); // This is the product "T * S" in Equation (A.16) on page 209 Matrix TS = LinearAlgebra::Product( - GeometryToolbox::CreateTranslationMatrix(static_cast<double>(intermediateWidth_) / 2.0, - static_cast<double>(intermediateHeight_) / 2.0, 0), - GeometryToolbox::CreateScalingMatrix(1.0 / maxScaling, 1.0 / maxScaling, 1), - GeometryToolbox::CreateTranslationMatrix(-extent.GetCenterX(), -extent.GetCenterY(), 0)); + GeometryToolbox::CreateTranslationMatrix( + static_cast<double>(intermediateWidth_) / 2.0, + static_cast<double>(intermediateHeight_) / 2.0, 0), + GeometryToolbox::CreateScalingMatrix( + 1.0 / maxScaling, 1.0 / maxScaling, 1), + GeometryToolbox::CreateTranslationMatrix( + -extent.GetCenterX(), -extent.GetCenterY(), 0)); // This is Equation (A.16) on page 209. WARNING: There is an // error in Lacroute's thesis: "inv(MM_shear)" is used instead @@ -380,8 +385,8 @@ // Compute the "world" matrix that maps the source volume to the // (0,0,0)->(1,1,1) unit cube - Vector origin = source.GetCoordinates(0, 0, 0); - Vector ps = source.GetVoxelDimensions(VolumeProjection_Axial); + Vector origin = source.GetGeometry().GetCoordinates(0, 0, 0); + Vector ps = source.GetGeometry().GetVoxelDimensions(VolumeProjection_Axial); Matrix world = LinearAlgebra::Product( GeometryToolbox::CreateScalingMatrix(1.0 / ps[0], 1.0 / ps[1], 1.0 / ps[2]), GeometryToolbox::CreateTranslationMatrix(-origin[0], -origin[1], -origin[2])); @@ -538,7 +543,8 @@ } else { - *p = *qacc / static_cast<float>(*qcount); + *p = static_cast<typename TargetTraits::PixelType> + (*qacc / static_cast<float>(*qcount)); if (*p > maxValue) {
--- a/Framework/Toolbox/Slice.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/Slice.cpp Tue May 21 13:25:58 2019 +0200 @@ -30,7 +30,7 @@ #include <boost/lexical_cast.hpp> -namespace OrthancStone +namespace Deprecated { static bool ParseDouble(double& target, const std::string& source) @@ -118,16 +118,16 @@ return false; } - if (!LinearAlgebra::IsCloseToZero(offset0)) + if (!OrthancStone::LinearAlgebra::IsCloseToZero(offset0)) { LOG(ERROR) << "Invalid syntax"; return false; } - geometry_ = CoordinateSystem3D(geometry_.GetOrigin() + z * geometry_.GetNormal(), - //+ 650 * geometry_.GetAxisX(), - geometry_.GetAxisX(), - geometry_.GetAxisY()); + geometry_ = OrthancStone::CoordinateSystem3D(geometry_.GetOrigin() + z * geometry_.GetNormal(), + //+ 650 * geometry_.GetAxisX(), + geometry_.GetAxisX(), + geometry_.GetAxisY()); thickness_ = offset1 - offset0; if (thickness_ < 0) @@ -185,19 +185,19 @@ converter_.ReadParameters(dataset); - GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dataset); + OrthancStone::GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dataset); std::string position, orientation; if (dataset.CopyToString(position, Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT, false) && dataset.CopyToString(orientation, Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT, false)) { - geometry_ = CoordinateSystem3D(position, orientation); + geometry_ = OrthancStone::CoordinateSystem3D(position, orientation); bool ok = true; - switch (StringToSopClassUid(sopClassUid_)) + switch (OrthancStone::StringToSopClassUid(sopClassUid_)) { - case SopClassUid_RTDose: + case OrthancStone::SopClassUid_RTDose: type_ = Type_OrthancRawFrame; ok = ComputeRTDoseGeometry(dataset, frame); break; @@ -243,7 +243,7 @@ } - const CoordinateSystem3D& Slice::GetGeometry() const + const OrthancStone::CoordinateSystem3D& Slice::GetGeometry() const { if (type_ == Type_Invalid) { @@ -320,7 +320,7 @@ } - bool Slice::ContainsPlane(const CoordinateSystem3D& plane) const + bool Slice::ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const { if (type_ == Type_Invalid) { @@ -328,16 +328,16 @@ } bool opposite; - return (GeometryToolbox::IsParallelOrOpposite(opposite, - GetGeometry().GetNormal(), - plane.GetNormal()) && - LinearAlgebra::IsNear(GetGeometry().ProjectAlongNormal(GetGeometry().GetOrigin()), - GetGeometry().ProjectAlongNormal(plane.GetOrigin()), - thickness_ / 2.0)); + return (OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, + GetGeometry().GetNormal(), + plane.GetNormal()) && + OrthancStone::LinearAlgebra::IsNear(GetGeometry().ProjectAlongNormal(GetGeometry().GetOrigin()), + GetGeometry().ProjectAlongNormal(plane.GetOrigin()), + thickness_ / 2.0)); } - void Slice::GetExtent(std::vector<Vector>& points) const + void Slice::GetExtent(std::vector<OrthancStone::Vector>& points) const { double sx = GetPixelSpacingX(); double sy = GetPixelSpacingY();
--- a/Framework/Toolbox/Slice.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/Slice.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ #include <Core/DicomFormat/DicomImageInformation.h> #include <Core/IDynamicObject.h> -namespace OrthancStone +namespace Deprecated { // TODO - Remove this class class Slice : @@ -51,7 +51,7 @@ std::string sopClassUid_; unsigned int frame_; unsigned int frameCount_; // TODO : Redundant with "imageInformation_" - CoordinateSystem3D geometry_; + OrthancStone::CoordinateSystem3D geometry_; double pixelSpacingX_; double pixelSpacingY_; double thickness_; @@ -79,7 +79,7 @@ // TODO Is this constructor the best way to go to tackle missing // layers within SliceViewerWidget? - Slice(const CoordinateSystem3D& plane, + Slice(const OrthancStone::CoordinateSystem3D& plane, double thickness) : type_(Type_Standalone), frame_(0), @@ -93,7 +93,7 @@ { } - Slice(const CoordinateSystem3D& plane, + Slice(const OrthancStone::CoordinateSystem3D& plane, double pixelSpacingX, double pixelSpacingY, double thickness, @@ -130,7 +130,7 @@ unsigned int GetFrame() const; - const CoordinateSystem3D& GetGeometry() const; + const OrthancStone::CoordinateSystem3D& GetGeometry() const; double GetThickness() const; @@ -144,9 +144,9 @@ const DicomFrameConverter& GetConverter() const; - bool ContainsPlane(const CoordinateSystem3D& plane) const; + bool ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const; - void GetExtent(std::vector<Vector>& points) const; + void GetExtent(std::vector<OrthancStone::Vector>& points) const; const Orthanc::DicomImageInformation& GetImageInformation() const;
--- a/Framework/Toolbox/SlicesSorter.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/SlicesSorter.h Tue May 21 13:25:58 2019 +0200 @@ -84,7 +84,8 @@ // slices. This is notably the case if all the slices are not // parallel to the reference normal that will be selected. bool Sort(); - + + // TODO - Remove this bool LookupClosestSlice(size_t& index, double& distance, const CoordinateSystem3D& slice) const;
--- a/Framework/Toolbox/ViewportGeometry.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/ViewportGeometry.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include <boost/math/special_functions/round.hpp> -namespace OrthancStone +namespace Deprecated { void ViewportGeometry::ComputeTransform() { @@ -79,7 +79,7 @@ } - void ViewportGeometry::SetSceneExtent(const Extent2D& extent) + void ViewportGeometry::SetSceneExtent(const OrthancStone::Extent2D& extent) { LOG(INFO) << "New scene extent: (" << extent.GetX1() << "," << extent.GetY1() << ") => (" @@ -128,7 +128,12 @@ sceneTouches.clear(); for (size_t t = 0; t < displayTouches.size(); t++) { - MapPixelCenterToScene(sceneX, sceneY, displayTouches[t].x, displayTouches[t].y); + MapPixelCenterToScene( + sceneX, + sceneY, + static_cast<int>(displayTouches[t].x), + static_cast<int>(displayTouches[t].y)); + sceneTouches.push_back(Touch((float)sceneX, (float)sceneY)); } } @@ -163,7 +168,7 @@ } - void ViewportGeometry::ApplyTransform(CairoContext& context) const + void ViewportGeometry::ApplyTransform(OrthancStone::CairoContext& context) const { cairo_set_matrix(context.GetObject(), &transform_); } @@ -193,9 +198,9 @@ } - Matrix ViewportGeometry::GetMatrix() const + OrthancStone::Matrix ViewportGeometry::GetMatrix() const { - Matrix m(3, 3); + OrthancStone::Matrix m(3, 3); m(0, 0) = transform_.xx; m(0, 1) = transform_.xy;
--- a/Framework/Toolbox/ViewportGeometry.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Toolbox/ViewportGeometry.h Tue May 21 13:25:58 2019 +0200 @@ -26,13 +26,13 @@ #include "LinearAlgebra.h" #include "../Viewport/IMouseTracker.h" // to include "Touch" definition -namespace OrthancStone +namespace Deprecated { class ViewportGeometry { private: // Extent of the scene (in world units) - Extent2D sceneExtent_; + OrthancStone::Extent2D sceneExtent_; // Size of the display (in pixels) unsigned int width_; @@ -53,9 +53,9 @@ void SetDisplaySize(unsigned int width, unsigned int height); - void SetSceneExtent(const Extent2D& extent); + void SetSceneExtent(const OrthancStone::Extent2D& extent); - const Extent2D& GetSceneExtent() const + const OrthancStone::Extent2D& GetSceneExtent() const { return sceneExtent_; } @@ -95,7 +95,7 @@ void FitContent(); - void ApplyTransform(CairoContext& context) const; + void ApplyTransform(OrthancStone::CairoContext& context) const; void GetPan(double& x, double& y) const; @@ -105,6 +105,6 @@ void SetZoom(double zoom); - Matrix GetMatrix() const; + OrthancStone::Matrix GetMatrix() const; }; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Toolbox/VolumeImageGeometry.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,309 @@ +/** + * 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 "VolumeImageGeometry.h" + +#include "../Toolbox/GeometryToolbox.h" + +#include <Core/OrthancException.h> + + +namespace OrthancStone +{ + void VolumeImageGeometry::Invalidate() + { + Vector p = (axialGeometry_.GetOrigin() + + static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal()); + + coronalGeometry_ = CoordinateSystem3D(p, + axialGeometry_.GetAxisX(), + -axialGeometry_.GetNormal()); + + sagittalGeometry_ = CoordinateSystem3D(p, + axialGeometry_.GetAxisY(), + axialGeometry_.GetNormal()); + + Vector origin = ( + axialGeometry_.MapSliceToWorldCoordinates(-0.5 * voxelDimensions_[0], + -0.5 * voxelDimensions_[1]) - + 0.5 * voxelDimensions_[2] * axialGeometry_.GetNormal()); + + Vector scaling; + + if (width_ == 0 || + height_ == 0 || + depth_ == 0) + { + LinearAlgebra::AssignVector(scaling, 1, 1, 1); + } + else + { + scaling = ( + axialGeometry_.GetAxisX() * voxelDimensions_[0] * static_cast<double>(width_) + + axialGeometry_.GetAxisY() * voxelDimensions_[1] * static_cast<double>(height_) + + axialGeometry_.GetNormal() * voxelDimensions_[2] * static_cast<double>(depth_)); + } + + transform_ = LinearAlgebra::Product( + GeometryToolbox::CreateTranslationMatrix(origin[0], origin[1], origin[2]), + GeometryToolbox::CreateScalingMatrix(scaling[0], scaling[1], scaling[2])); + + LinearAlgebra::InvertMatrix(transformInverse_, transform_); + } + + + VolumeImageGeometry::VolumeImageGeometry() : + width_(0), + height_(0), + depth_(0) + { + LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); + Invalidate(); + } + + + void VolumeImageGeometry::SetSize(unsigned int width, + unsigned int height, + unsigned int depth) + { + width_ = width; + height_ = height; + depth_ = depth; + Invalidate(); + } + + + void VolumeImageGeometry::SetAxialGeometry(const CoordinateSystem3D& geometry) + { + axialGeometry_ = geometry; + Invalidate(); + } + + + void VolumeImageGeometry::SetVoxelDimensions(double x, + double y, + double z) + { + if (x <= 0 || + y <= 0 || + z <= 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else + { + LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); + Invalidate(); + } + } + + + const CoordinateSystem3D& VolumeImageGeometry::GetProjectionGeometry(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return axialGeometry_; + + case VolumeProjection_Coronal: + return coronalGeometry_; + + case VolumeProjection_Sagittal: + return sagittalGeometry_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + Vector VolumeImageGeometry::GetVoxelDimensions(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return voxelDimensions_; + + case VolumeProjection_Coronal: + return LinearAlgebra::CreateVector(voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); + + case VolumeProjection_Sagittal: + return LinearAlgebra::CreateVector(voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionWidth(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return width_; + + case VolumeProjection_Coronal: + return width_; + + case VolumeProjection_Sagittal: + return height_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionHeight(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return height_; + + case VolumeProjection_Coronal: + return depth_; + + case VolumeProjection_Sagittal: + return depth_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionDepth(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return depth_; + + case VolumeProjection_Coronal: + return height_; + + case VolumeProjection_Sagittal: + return width_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + Vector VolumeImageGeometry::GetCoordinates(float x, + float y, + float z) const + { + Vector p = LinearAlgebra::Product(transform_, LinearAlgebra::CreateVector(x, y, z, 1)); + + assert(LinearAlgebra::IsNear(p[3], 1)); // Affine transform, no perspective effect + + // Back to non-homogeneous coordinates + return LinearAlgebra::CreateVector(p[0], p[1], p[2]); + } + + + bool VolumeImageGeometry::DetectProjection(VolumeProjection& projection, + const Vector& planeNormal) const + { + if (GeometryToolbox::IsParallel(planeNormal, axialGeometry_.GetNormal())) + { + projection = VolumeProjection_Axial; + return true; + } + else if (GeometryToolbox::IsParallel(planeNormal, coronalGeometry_.GetNormal())) + { + projection = VolumeProjection_Coronal; + return true; + } + else if (GeometryToolbox::IsParallel(planeNormal, sagittalGeometry_.GetNormal())) + { + projection = VolumeProjection_Sagittal; + return true; + } + else + { + return false; + } + } + + + bool VolumeImageGeometry::DetectSlice(VolumeProjection& projection, + unsigned int& slice, + const CoordinateSystem3D& plane) const + { + if (!DetectProjection(projection, plane.GetNormal())) + { + return false; + } + + // Transforms the coordinates of the origin of the plane, into the + // coordinates of the axial geometry + const Vector& origin = plane.GetOrigin(); + Vector p = LinearAlgebra::Product( + transformInverse_, + LinearAlgebra::CreateVector(origin[0], origin[1], origin[2], 1)); + + assert(LinearAlgebra::IsNear(p[3], 1)); + + double z; + + switch (projection) + { + case VolumeProjection_Axial: + z = p[2]; + break; + + case VolumeProjection_Coronal: + z = p[1]; + break; + + case VolumeProjection_Sagittal: + z = p[0]; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + const unsigned int projectionDepth = GetProjectionDepth(projection); + + z *= static_cast<double>(projectionDepth); + if (z < 0) + { + return false; + } + + unsigned int d = static_cast<unsigned int>(std::floor(z)); + if (d >= projectionDepth) + { + return false; + } + else + { + slice = d; + return true; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Toolbox/VolumeImageGeometry.h Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,122 @@ +/** + * 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 "../StoneEnumerations.h" +#include "CoordinateSystem3D.h" + +namespace OrthancStone +{ + class VolumeImageGeometry + { + private: + unsigned int width_; + unsigned int height_; + unsigned int depth_; + CoordinateSystem3D axialGeometry_; + CoordinateSystem3D coronalGeometry_; + CoordinateSystem3D sagittalGeometry_; + Vector voxelDimensions_; + Matrix transform_; + Matrix transformInverse_; + + void Invalidate(); + + public: + VolumeImageGeometry(); + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + unsigned int GetDepth() const + { + return depth_; + } + + const CoordinateSystem3D& GetAxialGeometry() const + { + return axialGeometry_; + } + + const CoordinateSystem3D& GetCoronalGeometry() const + { + return coronalGeometry_; + } + + const CoordinateSystem3D& GetSagittalGeometry() const + { + return sagittalGeometry_; + } + + const CoordinateSystem3D& GetProjectionGeometry(VolumeProjection projection) const; + + const Matrix& GetTransform() const + { + return transform_; + } + + const Matrix& GetTransformInverse() const + { + return transformInverse_; + } + + void SetSize(unsigned int width, + unsigned int height, + unsigned int depth); + + // Set the geometry of the first axial slice (i.e. the one whose + // depth == 0) + void SetAxialGeometry(const CoordinateSystem3D& geometry); + + void SetVoxelDimensions(double x, + double y, + double z); + + Vector GetVoxelDimensions(VolumeProjection projection) const; + + unsigned int GetProjectionWidth(VolumeProjection projection) const; + + unsigned int GetProjectionHeight(VolumeProjection projection) const; + + unsigned int GetProjectionDepth(VolumeProjection projection) const; + + // Get the 3D position of a point in the volume, where x, y and z + // lie in the [0;1] range + Vector GetCoordinates(float x, + float y, + float z) const; + + bool DetectProjection(VolumeProjection& projection, + const Vector& planeNormal) const; + + bool DetectSlice(VolumeProjection& projection, + unsigned int& slice, + const CoordinateSystem3D& plane) const; + }; +}
--- a/Framework/Viewport/IMouseTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Viewport/IMouseTracker.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include "CairoSurface.h" #include <vector> -namespace OrthancStone +namespace Deprecated { struct Touch {
--- a/Framework/Viewport/IStatusBar.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Viewport/IStatusBar.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <string> #include <boost/noncopyable.hpp> -namespace OrthancStone +namespace Deprecated { class IStatusBar : public boost::noncopyable {
--- a/Framework/Viewport/IViewport.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Viewport/IViewport.h Tue May 21 13:25:58 2019 +0200 @@ -28,16 +28,16 @@ #include <Core/Images/ImageAccessor.h> #include "../Viewport/IMouseTracker.h" // only to get the "Touch" definition -namespace OrthancStone +namespace Deprecated { class IWidget; // Forward declaration - class IViewport : public IObservable + class IViewport : public OrthancStone::IObservable { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ViewportChangedMessage, IViewport); - IViewport(MessageBroker& broker) : + IViewport(OrthancStone::MessageBroker& broker) : IObservable(broker) { } @@ -56,10 +56,10 @@ // The function returns "true" iff. a new frame was rendered virtual bool Render(Orthanc::ImageAccessor& surface) = 0; - virtual void MouseDown(MouseButton button, + virtual void MouseDown(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) = 0; virtual void MouseUp() = 0; @@ -72,14 +72,14 @@ virtual void MouseLeave() = 0; - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) = 0; + OrthancStone::KeyboardModifiers modifiers) = 0; - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) = 0; + OrthancStone::KeyboardModifiers modifiers) = 0; virtual bool HasAnimation() = 0;
--- a/Framework/Viewport/WidgetViewport.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Viewport/WidgetViewport.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,9 +24,9 @@ #include <Core/Images/ImageProcessing.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { - WidgetViewport::WidgetViewport(MessageBroker& broker) : + WidgetViewport::WidgetViewport(OrthancStone::MessageBroker& broker) : IViewport(broker), statusBar_(NULL), isMouseOver_(false), @@ -139,7 +139,7 @@ void WidgetViewport::TouchStart(const std::vector<Touch>& displayTouches) { - MouseDown(MouseButton_Left, (int)displayTouches[0].x, (int)displayTouches[0].y, KeyboardModifiers_None, displayTouches); // one touch is equivalent to a mouse tracker without left button -> set the mouse coordinates to the first touch coordinates + MouseDown(OrthancStone::MouseButton_Left, (int)displayTouches[0].x, (int)displayTouches[0].y, OrthancStone::KeyboardModifiers_None, displayTouches); // one touch is equivalent to a mouse tracker without left button -> set the mouse coordinates to the first touch coordinates } void WidgetViewport::TouchMove(const std::vector<Touch>& displayTouches) @@ -154,10 +154,10 @@ MouseUp(); } - void WidgetViewport::MouseDown(MouseButton button, + void WidgetViewport::MouseDown(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& displayTouches ) { @@ -241,10 +241,10 @@ } - void WidgetViewport::MouseWheel(MouseWheelDirection direction, + void WidgetViewport::MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { if (centralWidget_.get() != NULL && mouseTracker_.get() == NULL) @@ -254,9 +254,9 @@ } - void WidgetViewport::KeyPressed(KeyboardKeys key, + void WidgetViewport::KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { if (centralWidget_.get() != NULL && mouseTracker_.get() == NULL)
--- a/Framework/Viewport/WidgetViewport.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Viewport/WidgetViewport.h Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include <memory> -namespace OrthancStone +namespace Deprecated { class WidgetViewport : public IViewport { @@ -37,11 +37,11 @@ bool isMouseOver_; int lastMouseX_; int lastMouseY_; - CairoSurface background_; + OrthancStone::CairoSurface background_; bool backgroundChanged_; public: - WidgetViewport(MessageBroker& broker); + WidgetViewport(OrthancStone::MessageBroker& broker); virtual void FitContent(); @@ -56,10 +56,10 @@ virtual bool Render(Orthanc::ImageAccessor& surface); - virtual void MouseDown(MouseButton button, + virtual void MouseDown(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& displayTouches); virtual void MouseUp(); @@ -78,14 +78,14 @@ virtual void TouchEnd(const std::vector<Touch>& touches); - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); virtual bool HasAnimation();
--- a/Framework/Volumes/ISlicedVolume.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/ISlicedVolume.h Tue May 21 13:25:58 2019 +0200 @@ -24,9 +24,9 @@ #include "../Messages/IObservable.h" #include "../Toolbox/Slice.h" -namespace OrthancStone +namespace Deprecated { - class ISlicedVolume : public IObservable + class ISlicedVolume : public OrthancStone::IObservable { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, ISlicedVolume); @@ -35,7 +35,7 @@ ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, VolumeReadyMessage, ISlicedVolume); - class SliceContentChangedMessage : public OriginMessage<ISlicedVolume> + class SliceContentChangedMessage : public OrthancStone::OriginMessage<ISlicedVolume> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); @@ -65,7 +65,7 @@ }; - ISlicedVolume(MessageBroker& broker) : + ISlicedVolume(OrthancStone::MessageBroker& broker) : IObservable(broker) { }
--- a/Framework/Volumes/IVolumeLoader.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/IVolumeLoader.h Tue May 21 13:25:58 2019 +0200 @@ -23,16 +23,16 @@ #include "../Messages/IObservable.h" -namespace OrthancStone +namespace Deprecated { - class IVolumeLoader : public IObservable + class IVolumeLoader : public OrthancStone::IObservable { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryReadyMessage, IVolumeLoader); ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryErrorMessage, IVolumeLoader); ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, ContentChangedMessage, IVolumeLoader); - IVolumeLoader(MessageBroker& broker) : + IVolumeLoader(OrthancStone::MessageBroker& broker) : IObservable(broker) { }
--- a/Framework/Volumes/ImageBuffer3D.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/ImageBuffer3D.cpp Tue May 21 13:25:58 2019 +0200 @@ -21,6 +21,8 @@ #include "ImageBuffer3D.h" +#include "../Toolbox/GeometryToolbox.h" + #include <Core/Images/ImageProcessing.h> #include <Core/Logging.h> #include <Core/OrthancException.h> @@ -116,7 +118,7 @@ computeRange_(computeRange), hasRange_(false) { - LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); + geometry_.SetSize(width, height, depth); LOG(INFO) << "Created a 3D image of size " << width << "x" << height << "x" << depth << " in " << Orthanc::EnumerationToString(format) @@ -130,127 +132,57 @@ } - void ImageBuffer3D::SetAxialGeometry(const CoordinateSystem3D& geometry) - { - axialGeometry_ = geometry; - } - - - void ImageBuffer3D::SetVoxelDimensions(double x, - double y, - double z) - { - if (x <= 0 || - y <= 0 || - z <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - { - LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); - } - } - - - Vector ImageBuffer3D::GetVoxelDimensions(VolumeProjection projection) const - { - Vector result; - switch (projection) - { - case VolumeProjection_Axial: - result = voxelDimensions_; - break; - - case VolumeProjection_Coronal: - LinearAlgebra::AssignVector(result, voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); - break; - - case VolumeProjection_Sagittal: - LinearAlgebra::AssignVector(result, voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - return result; - } - - - void ImageBuffer3D::GetSliceSize(unsigned int& width, - unsigned int& height, - VolumeProjection projection) - { - switch (projection) - { - case VolumeProjection_Axial: - width = width_; - height = height_; - break; - - case VolumeProjection_Coronal: - width = width_; - height = depth_; - break; - - case VolumeProjection_Sagittal: - width = height_; - height = depth_; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } ParallelSlices* ImageBuffer3D::GetGeometry(VolumeProjection projection) const { + const Vector dimensions = geometry_.GetVoxelDimensions(VolumeProjection_Axial); + const CoordinateSystem3D& axial = geometry_.GetAxialGeometry(); + std::auto_ptr<ParallelSlices> result(new ParallelSlices); switch (projection) { - case VolumeProjection_Axial: - for (unsigned int z = 0; z < depth_; z++) - { - Vector origin = axialGeometry_.GetOrigin(); - origin += static_cast<double>(z) * voxelDimensions_[2] * axialGeometry_.GetNormal(); + case VolumeProjection_Axial: + for (unsigned int z = 0; z < depth_; z++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast<double>(z) * dimensions[2] * axial.GetNormal(); - result->AddSlice(origin, - axialGeometry_.GetAxisX(), - axialGeometry_.GetAxisY()); - } - break; + result->AddSlice(origin, + axial.GetAxisX(), + axial.GetAxisY()); + } + break; - case VolumeProjection_Coronal: - for (unsigned int y = 0; y < height_; y++) - { - Vector origin = axialGeometry_.GetOrigin(); - origin += static_cast<double>(y) * voxelDimensions_[1] * axialGeometry_.GetAxisY(); - origin += static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal(); + case VolumeProjection_Coronal: + for (unsigned int y = 0; y < height_; y++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast<double>(y) * dimensions[1] * axial.GetAxisY(); + origin += static_cast<double>(depth_ - 1) * dimensions[2] * axial.GetNormal(); - result->AddSlice(origin, - axialGeometry_.GetAxisX(), - -axialGeometry_.GetNormal()); - } - break; + result->AddSlice(origin, + axial.GetAxisX(), + -axial.GetNormal()); + } + break; - case VolumeProjection_Sagittal: - for (unsigned int x = 0; x < width_; x++) - { - Vector origin = axialGeometry_.GetOrigin(); - origin += static_cast<double>(x) * voxelDimensions_[0] * axialGeometry_.GetAxisX(); - origin += static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal(); + case VolumeProjection_Sagittal: + for (unsigned int x = 0; x < width_; x++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast<double>(x) * dimensions[0] * axial.GetAxisX(); + origin += static_cast<double>(depth_ - 1) * dimensions[2] * axial.GetNormal(); - result->AddSlice(origin, - axialGeometry_.GetAxisY(), - -axialGeometry_.GetNormal()); - } - break; + result->AddSlice(origin, + axial.GetAxisY(), + -axial.GetNormal()); + } + break; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } return result.release(); @@ -276,24 +208,24 @@ switch (slice.GetFormat()) { - case Orthanc::PixelFormat_Grayscale8: - case Orthanc::PixelFormat_Grayscale16: - case Orthanc::PixelFormat_Grayscale32: - case Orthanc::PixelFormat_SignedGrayscale16: - { - int64_t a, b; - Orthanc::ImageProcessing::GetMinMaxIntegerValue(a, b, slice); - sliceMin = static_cast<float>(a); - sliceMax = static_cast<float>(b); - break; - } + case Orthanc::PixelFormat_Grayscale8: + case Orthanc::PixelFormat_Grayscale16: + case Orthanc::PixelFormat_Grayscale32: + case Orthanc::PixelFormat_SignedGrayscale16: + { + int64_t a, b; + Orthanc::ImageProcessing::GetMinMaxIntegerValue(a, b, slice); + sliceMin = static_cast<float>(a); + sliceMax = static_cast<float>(b); + break; + } - case Orthanc::PixelFormat_Float32: - Orthanc::ImageProcessing::GetMinMaxFloatValue(sliceMin, sliceMax, slice); - break; + case Orthanc::PixelFormat_Float32: + Orthanc::ImageProcessing::GetMinMaxFloatValue(sliceMin, sliceMax, slice); + break; - default: - return; + default: + return; } if (hasRange_) @@ -326,14 +258,21 @@ } - bool ImageBuffer3D::FitWindowingToRange(RenderStyle& style, - const DicomFrameConverter& converter) const + bool ImageBuffer3D::FitWindowingToRange(Deprecated::RenderStyle& style, + const Deprecated::DicomFrameConverter& converter) const { if (hasRange_) { style.windowing_ = ImageWindowing_Custom; - style.customWindowCenter_ = converter.Apply((minValue_ + maxValue_) / 2.0); - style.customWindowWidth_ = converter.Apply(maxValue_ - minValue_); + + // casting the narrower type to wider before calling the + operator + // will prevent overflowing (this is why the cast to double is only + // done on the first operand) + style.customWindowCenter_ = static_cast<float>( + converter.Apply((static_cast<double>(minValue_) + maxValue_) / 2.0)); + + style.customWindowWidth_ = static_cast<float>( + converter.Apply(static_cast<double>(maxValue_) - minValue_)); if (style.customWindowWidth_ > 1) { @@ -367,8 +306,8 @@ sagittal_->GetReadOnlyAccessor(accessor_); break; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } } @@ -411,8 +350,8 @@ sagittal_->GetWriteableAccessor(accessor_); break; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } } @@ -457,22 +396,4 @@ const void* p = image_.GetConstRow(y + height_ * (depth_ - 1 - z)); return reinterpret_cast<const uint16_t*>(p) [x]; } - - - Vector ImageBuffer3D::GetCoordinates(float x, - float y, - float z) const - { - Vector ps = GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); - - const CoordinateSystem3D& axial = GetAxialGeometry(); - - Vector origin = (axial.MapSliceToWorldCoordinates(-0.5 * ps[0], -0.5 * ps[1]) - - 0.5 * ps[2] * axial.GetNormal()); - - return (origin + - axial.GetAxisX() * ps[0] * x * static_cast<double>(GetWidth()) + - axial.GetAxisY() * ps[1] * y * static_cast<double>(GetHeight()) + - axial.GetNormal() * ps[2] * z * static_cast<double>(GetDepth())); - } }
--- a/Framework/Volumes/ImageBuffer3D.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/ImageBuffer3D.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "../StoneEnumerations.h" #include "../Layers/RenderStyle.h" -#include "../Toolbox/CoordinateSystem3D.h" +#include "../Toolbox/VolumeImageGeometry.h" #include "../Toolbox/DicomFrameConverter.h" #include "../Toolbox/ParallelSlices.h" @@ -34,8 +34,7 @@ class ImageBuffer3D : public boost::noncopyable { private: - CoordinateSystem3D axialGeometry_; - Vector voxelDimensions_; + VolumeImageGeometry geometry_; // TODO => Move this out of this class Orthanc::Image image_; Orthanc::PixelFormat format_; unsigned int width_; @@ -45,6 +44,8 @@ bool hasRange_; float minValue_; float maxValue_; + Matrix transform_; + Matrix transformInverse_; void ExtendImageRange(const Orthanc::ImageAccessor& slice); @@ -77,24 +78,15 @@ void Clear(); - // Set the geometry of the first axial slice (i.e. the one whose - // depth == 0) - void SetAxialGeometry(const CoordinateSystem3D& geometry); - - const CoordinateSystem3D& GetAxialGeometry() const + VolumeImageGeometry& GetGeometry() { - return axialGeometry_; + return geometry_; } - void SetVoxelDimensions(double x, - double y, - double z); - - Vector GetVoxelDimensions(VolumeProjection projection) const; - - void GetSliceSize(unsigned int& width, - unsigned int& height, - VolumeProjection projection); + const VolumeImageGeometry& GetGeometry() const + { + return geometry_; + } const Orthanc::ImageAccessor& GetInternalImage() const { @@ -121,6 +113,7 @@ return format_; } + // TODO - Remove ParallelSlices* GetGeometry(VolumeProjection projection) const; uint64_t GetEstimatedMemorySize() const; @@ -128,8 +121,8 @@ bool GetRange(float& minValue, float& maxValue) const; - bool FitWindowingToRange(RenderStyle& style, - const DicomFrameConverter& converter) const; + bool FitWindowingToRange(Deprecated::RenderStyle& style, + const Deprecated::DicomFrameConverter& converter) const; uint8_t GetVoxelGrayscale8Unchecked(unsigned int x, unsigned int y, @@ -160,13 +153,7 @@ unsigned int y, unsigned int z) const; - // Get the 3D position of a point in the volume, where x, y and z - // lie in the [0;1] range - Vector GetCoordinates(float x, - float y, - float z) const; - - + class SliceReader : public boost::noncopyable { private:
--- a/Framework/Volumes/StructureSetLoader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/StructureSetLoader.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,9 +25,9 @@ #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { - StructureSetLoader::StructureSetLoader(MessageBroker& broker, + StructureSetLoader::StructureSetLoader(OrthancStone::MessageBroker& broker, OrthancApiClient& orthanc) : IVolumeLoader(broker), IObserver(broker), @@ -41,7 +41,7 @@ OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); Orthanc::DicomMap slice; - MessagingToolbox::ConvertDataset(slice, dataset); + OrthancStone::MessagingToolbox::ConvertDataset(slice, dataset); structureSet_->AddReferencedSlice(slice); BroadcastMessage(ContentChangedMessage(*this)); @@ -51,7 +51,7 @@ void StructureSetLoader::OnStructureSetLoaded(const OrthancApiClient::JsonResponseReadyMessage& message) { OrthancPlugins::FullOrthancDataset dataset(message.GetJson()); - structureSet_.reset(new DicomStructureSet(dataset)); + structureSet_.reset(new OrthancStone::DicomStructureSet(dataset)); std::set<std::string> instances; structureSet_->GetReferencedInstances(instances); @@ -60,7 +60,7 @@ it != instances.end(); ++it) { orthanc_.PostBinaryAsyncExpectJson("/tools/lookup", *it, - new Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnLookupCompleted)); + new OrthancStone::Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnLookupCompleted)); } BroadcastMessage(GeometryReadyMessage(*this)); @@ -84,7 +84,7 @@ const std::string& instance = lookup[0]["ID"].asString(); orthanc_.GetJsonAsync("/instances/" + instance + "/tags", - new Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnReferencedSliceLoaded)); + new OrthancStone::Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnReferencedSliceLoaded)); } @@ -97,12 +97,12 @@ else { orthanc_.GetJsonAsync("/instances/" + instance + "/tags?ignore-length=3006-0050", - new Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnStructureSetLoaded)); + new OrthancStone::Callable<StructureSetLoader, OrthancApiClient::JsonResponseReadyMessage>(*this, &StructureSetLoader::OnStructureSetLoaded)); } } - DicomStructureSet& StructureSetLoader::GetStructureSet() + OrthancStone::DicomStructureSet& StructureSetLoader::GetStructureSet() { if (structureSet_.get() == NULL) {
--- a/Framework/Volumes/StructureSetLoader.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/StructureSetLoader.h Tue May 21 13:25:58 2019 +0200 @@ -25,15 +25,15 @@ #include "../Toolbox/OrthancApiClient.h" #include "IVolumeLoader.h" -namespace OrthancStone +namespace Deprecated { class StructureSetLoader : public IVolumeLoader, - public IObserver + public OrthancStone::IObserver { private: OrthancApiClient& orthanc_; - std::auto_ptr<DicomStructureSet> structureSet_; + std::auto_ptr<OrthancStone::DicomStructureSet> structureSet_; void OnReferencedSliceLoaded(const OrthancApiClient::JsonResponseReadyMessage& message); @@ -42,7 +42,7 @@ void OnLookupCompleted(const OrthancApiClient::JsonResponseReadyMessage& message); public: - StructureSetLoader(MessageBroker& broker, + StructureSetLoader(OrthancStone::MessageBroker& broker, OrthancApiClient& orthanc); void ScheduleLoadInstance(const std::string& instance); @@ -52,6 +52,6 @@ return structureSet_.get() != NULL; } - DicomStructureSet& GetStructureSet(); + OrthancStone::DicomStructureSet& GetStructureSet(); }; }
--- a/Framework/Volumes/VolumeReslicer.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Volumes/VolumeReslicer.cpp Tue May 21 13:25:58 2019 +0200 @@ -749,7 +749,8 @@ { // Choose the default voxel size as the finest voxel dimension // of the source volumetric image - const OrthancStone::Vector dim = source.GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); + const OrthancStone::Vector dim = + source.GetGeometry().GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); double voxelSize = dim[0]; if (dim[1] < voxelSize)
--- a/Framework/Widgets/CairoWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/CairoWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <Core/Images/ImageProcessing.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { static bool IsAligned(const Orthanc::ImageAccessor& target) { @@ -51,14 +51,14 @@ if (IsAligned(target)) { - CairoSurface surface(target, false /* no alpha */); - CairoContext context(surface); + OrthancStone::CairoSurface surface(target, false /* no alpha */); + OrthancStone::CairoContext context(surface); ClearBackgroundCairo(context); return RenderCairo(context); } else { - CairoContext context(surface_); + OrthancStone::CairoContext context(surface_); ClearBackgroundCairo(context); if (RenderCairo(context)) @@ -82,8 +82,8 @@ { if (IsAligned(target)) { - CairoSurface surface(target, false /* no alpha */); - CairoContext context(surface); + OrthancStone::CairoSurface surface(target, false /* no alpha */); + OrthancStone::CairoContext context(surface); RenderMouseOverCairo(context, x, y); } else @@ -92,7 +92,7 @@ surface_.GetWriteableAccessor(accessor); Orthanc::ImageProcessing::Copy(accessor, target); - CairoContext context(surface_); + OrthancStone::CairoContext context(surface_); RenderMouseOverCairo(context, x, y); Orthanc::ImageProcessing::Copy(target, accessor);
--- a/Framework/Widgets/CairoWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/CairoWidget.h Tue May 21 13:25:58 2019 +0200 @@ -23,17 +23,17 @@ #include "WidgetBase.h" -namespace OrthancStone +namespace Deprecated { class CairoWidget : public WidgetBase { private: - CairoSurface surface_; + OrthancStone::CairoSurface surface_; protected: - virtual bool RenderCairo(CairoContext& context) = 0; + virtual bool RenderCairo(OrthancStone::CairoContext& context) = 0; - virtual void RenderMouseOverCairo(CairoContext& context, + virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, int x, int y) = 0;
--- a/Framework/Widgets/EmptyWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/EmptyWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <Core/Images/ImageProcessing.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { bool EmptyWidget::Render(Orthanc::ImageAccessor& surface) {
--- a/Framework/Widgets/EmptyWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/EmptyWidget.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "IWidget.h" -namespace OrthancStone +namespace Deprecated { /** * This is a test widget that simply fills its surface with an @@ -73,10 +73,10 @@ virtual bool Render(Orthanc::ImageAccessor& surface); - virtual IMouseTracker* CreateMouseTracker(MouseButton button, + virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) { return NULL; @@ -88,16 +88,16 @@ { } - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { } - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { }
--- a/Framework/Widgets/IWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/IWidget.h Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include "../Viewport/IMouseTracker.h" #include "../Viewport/IStatusBar.h" -namespace OrthancStone +namespace Deprecated { class WidgetViewport; // Forward declaration @@ -49,10 +49,10 @@ virtual bool Render(Orthanc::ImageAccessor& surface) = 0; - virtual IMouseTracker* CreateMouseTracker(MouseButton button, + virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) = 0; virtual void RenderMouseOver(Orthanc::ImageAccessor& target, @@ -61,14 +61,14 @@ virtual bool HasRenderMouseOver() = 0; - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) = 0; + OrthancStone::KeyboardModifiers modifiers) = 0; - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) = 0; + OrthancStone::KeyboardModifiers modifiers) = 0; virtual bool HasAnimation() const = 0;
--- a/Framework/Widgets/IWorldSceneInteractor.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/IWorldSceneInteractor.h Tue May 21 13:25:58 2019 +0200 @@ -27,7 +27,7 @@ #include "../StoneEnumerations.h" #include "../Viewport/IStatusBar.h" -namespace OrthancStone +namespace Deprecated { class WorldSceneWidget; @@ -40,8 +40,8 @@ virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, + OrthancStone::MouseButton button, + OrthancStone::KeyboardModifiers modifiers, int viewportX, int viewportY, double x, @@ -49,7 +49,7 @@ IStatusBar* statusBar, const std::vector<Touch>& touches) = 0; - virtual void MouseOver(CairoContext& context, + virtual void MouseOver(OrthancStone::CairoContext& context, WorldSceneWidget& widget, const ViewportGeometry& view, double x, @@ -57,14 +57,14 @@ IStatusBar* statusBar) = 0; virtual void MouseWheel(WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, + OrthancStone::MouseWheelDirection direction, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) = 0; virtual void KeyPressed(WorldSceneWidget& widget, - KeyboardKeys key, + OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) = 0; }; }
--- a/Framework/Widgets/IWorldSceneMouseTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/IWorldSceneMouseTracker.h Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include "../Viewport/CairoContext.h" #include "../Viewport/IMouseTracker.h" // only to get the "Touch" definition -namespace OrthancStone +namespace Deprecated { // this is tracking a mouse in scene coordinates/mm unlike @@ -39,7 +39,7 @@ virtual bool HasRender() const = 0; - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom) = 0; virtual void MouseUp() = 0;
--- a/Framework/Widgets/LayoutWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/LayoutWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include <boost/math/special_functions/round.hpp> -namespace OrthancStone +namespace Deprecated { class LayoutWidget::LayoutMouseTracker : public IMouseTracker { @@ -154,10 +154,10 @@ } } - IMouseTracker* CreateMouseTracker(MouseButton button, + IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) { if (Contains(x, y)) @@ -189,10 +189,10 @@ } } - void MouseWheel(MouseWheelDirection direction, + void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { if (Contains(x, y)) { @@ -419,10 +419,10 @@ } - IMouseTracker* LayoutWidget::CreateMouseTracker(MouseButton button, + IMouseTracker* LayoutWidget::CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) { for (size_t i = 0; i < children_.size(); i++) @@ -449,10 +449,10 @@ } - void LayoutWidget::MouseWheel(MouseWheelDirection direction, + void LayoutWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { for (size_t i = 0; i < children_.size(); i++) { @@ -461,9 +461,9 @@ } - void LayoutWidget::KeyPressed(KeyboardKeys key, + void LayoutWidget::KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { for (size_t i = 0; i < children_.size(); i++) {
--- a/Framework/Widgets/LayoutWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/LayoutWidget.h Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include <vector> #include <memory> -namespace OrthancStone +namespace Deprecated { class LayoutWidget : public WidgetBase { @@ -103,24 +103,24 @@ virtual bool Render(Orthanc::ImageAccessor& surface); - virtual IMouseTracker* CreateMouseTracker(MouseButton button, + virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches); virtual void RenderMouseOver(Orthanc::ImageAccessor& target, int x, int y); - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); virtual bool HasAnimation() const {
--- a/Framework/Widgets/PanMouseTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/PanMouseTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <Core/Logging.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { PanMouseTracker::PanMouseTracker(WorldSceneWidget& that, int x, @@ -36,7 +36,7 @@ } - void PanMouseTracker::Render(CairoContext& context, + void PanMouseTracker::Render(OrthancStone::CairoContext& context, double zoom) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
--- a/Framework/Widgets/PanMouseTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/PanMouseTracker.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "WorldSceneWidget.h" -namespace OrthancStone +namespace Deprecated { class PanMouseTracker : public IWorldSceneMouseTracker { @@ -48,7 +48,7 @@ { } - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom); virtual void MouseMove(int displayX,
--- a/Framework/Widgets/PanZoomMouseTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/PanZoomMouseTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <Core/OrthancException.h> #include <math.h> -namespace OrthancStone +namespace Deprecated { Touch GetCenter(const std::vector<Touch>& touches) { @@ -75,7 +75,7 @@ } - void PanZoomMouseTracker::Render(CairoContext& context, + void PanZoomMouseTracker::Render(OrthancStone::CairoContext& context, double zoom) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
--- a/Framework/Widgets/PanZoomMouseTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/PanZoomMouseTracker.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "WorldSceneWidget.h" -namespace OrthancStone +namespace Deprecated { class PanZoomMouseTracker : public IWorldSceneMouseTracker { @@ -52,7 +52,7 @@ { } - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom); virtual void MouseMove(int displayX,
--- a/Framework/Widgets/SliceViewerWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/SliceViewerWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -33,12 +33,12 @@ static const double THIN_SLICE_THICKNESS = 100.0 * std::numeric_limits<double>::epsilon(); -namespace OrthancStone +namespace Deprecated { class SliceViewerWidget::Scene : public boost::noncopyable { private: - CoordinateSystem3D plane_; + OrthancStone::CoordinateSystem3D plane_; double thickness_; size_t countMissing_; std::vector<ILayerRenderer*> renderers_; @@ -62,7 +62,7 @@ } } - Scene(const CoordinateSystem3D& plane, + Scene(const OrthancStone::CoordinateSystem3D& plane, double thickness, size_t countLayers) : plane_(plane), @@ -98,7 +98,7 @@ countMissing_--; } - const CoordinateSystem3D& GetPlane() const + const OrthancStone::CoordinateSystem3D& GetPlane() const { return plane_; } @@ -115,12 +115,12 @@ unsigned int GetCountMissing() const { - return countMissing_; + return static_cast<unsigned int>(countMissing_); } - bool RenderScene(CairoContext& context, + bool RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view, - const CoordinateSystem3D& viewportPlane) + const OrthancStone::CoordinateSystem3D& viewportPlane) { bool fullQuality = true; cairo_t *cr = context.GetObject(); @@ -129,7 +129,7 @@ { if (renderers_[i] != NULL) { - const CoordinateSystem3D& framePlane = renderers_[i]->GetLayerPlane(); + const OrthancStone::CoordinateSystem3D& framePlane = renderers_[i]->GetLayerPlane(); double x0, y0, x1, y1, x2, y2; viewportPlane.ProjectPoint(x0, y0, framePlane.GetOrigin()); @@ -207,12 +207,12 @@ } } - bool ContainsPlane(const CoordinateSystem3D& plane) const + bool ContainsPlane(const OrthancStone::CoordinateSystem3D& plane) const { bool isOpposite; - if (!GeometryToolbox::IsParallelOrOpposite(isOpposite, - plane.GetNormal(), - plane_.GetNormal())) + if (!OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, + plane.GetNormal(), + plane_.GetNormal())) { return false; } @@ -256,12 +256,12 @@ } - void SliceViewerWidget::GetLayerExtent(Extent2D& extent, + void SliceViewerWidget::GetLayerExtent(OrthancStone::Extent2D& extent, IVolumeSlicer& source) const { extent.Reset(); - std::vector<Vector> points; + std::vector<OrthancStone::Vector> points; if (source.GetExtent(points, plane_)) { for (size_t i = 0; i < points.size(); i++) @@ -274,14 +274,14 @@ } - Extent2D SliceViewerWidget::GetSceneExtent() + OrthancStone::Extent2D SliceViewerWidget::GetSceneExtent() { - Extent2D sceneExtent; + OrthancStone::Extent2D sceneExtent; for (size_t i = 0; i < layers_.size(); i++) { assert(layers_[i] != NULL); - Extent2D layerExtent; + OrthancStone::Extent2D layerExtent; GetLayerExtent(layerExtent, *layers_[i]); sceneExtent.Union(layerExtent); @@ -291,7 +291,7 @@ } - bool SliceViewerWidget::RenderScene(CairoContext& context, + bool SliceViewerWidget::RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view) { if (currentScene_.get() != NULL) @@ -323,7 +323,7 @@ void SliceViewerWidget::UpdateLayer(size_t index, ILayerRenderer* renderer, - const CoordinateSystem3D& plane) + const OrthancStone::CoordinateSystem3D& plane) { LOG(INFO) << "Updating layer " << index; @@ -364,7 +364,7 @@ } - SliceViewerWidget::SliceViewerWidget(MessageBroker& broker, + SliceViewerWidget::SliceViewerWidget(OrthancStone::MessageBroker& broker, const std::string& name) : WorldSceneWidget(name), IObserver(broker), @@ -385,16 +385,16 @@ void SliceViewerWidget::ObserveLayer(IVolumeSlicer& layer) { - layer.RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::GeometryReadyMessage> + layer.RegisterObserverCallback(new OrthancStone::Callable<SliceViewerWidget, IVolumeSlicer::GeometryReadyMessage> (*this, &SliceViewerWidget::OnGeometryReady)); // currently ignore errors layer->RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::GeometryErrorMessage>(*this, &SliceViewerWidget::...)); - layer.RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::SliceContentChangedMessage> + layer.RegisterObserverCallback(new OrthancStone::Callable<SliceViewerWidget, IVolumeSlicer::SliceContentChangedMessage> (*this, &SliceViewerWidget::OnSliceChanged)); - layer.RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::ContentChangedMessage> + layer.RegisterObserverCallback(new OrthancStone::Callable<SliceViewerWidget, IVolumeSlicer::ContentChangedMessage> (*this, &SliceViewerWidget::OnContentChanged)); - layer.RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::LayerReadyMessage> + layer.RegisterObserverCallback(new OrthancStone::Callable<SliceViewerWidget, IVolumeSlicer::LayerReadyMessage> (*this, &SliceViewerWidget::OnLayerReady)); - layer.RegisterObserverCallback(new Callable<SliceViewerWidget, IVolumeSlicer::LayerErrorMessage> + layer.RegisterObserverCallback(new OrthancStone::Callable<SliceViewerWidget, IVolumeSlicer::LayerErrorMessage> (*this, &SliceViewerWidget::OnLayerError)); } @@ -504,13 +504,13 @@ } - void SliceViewerWidget::SetSlice(const CoordinateSystem3D& plane) + void SliceViewerWidget::SetSlice(const OrthancStone::CoordinateSystem3D& plane) { LOG(INFO) << "Setting slice origin: (" << plane.GetOrigin()[0] << "," << plane.GetOrigin()[1] << "," << plane.GetOrigin()[2] << ")"; - Slice displayedSlice(plane_, THIN_SLICE_THICKNESS); + Deprecated::Slice displayedSlice(plane_, THIN_SLICE_THICKNESS); //if (!displayedSlice.ContainsPlane(slice)) {
--- a/Framework/Widgets/SliceViewerWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/SliceViewerWidget.h Tue May 21 13:25:58 2019 +0200 @@ -28,12 +28,12 @@ #include <map> -namespace OrthancStone +namespace Deprecated { class SliceViewerWidget : public WorldSceneWidget, - public IObserver, - public IObservable + public OrthancStone::IObserver, + public OrthancStone::IObservable { public: ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, GeometryChangedMessage, SliceViewerWidget); @@ -41,22 +41,22 @@ // TODO - Use this message in ReferenceLineSource - class DisplayedSliceMessage : public OriginMessage<SliceViewerWidget> + class DisplayedSliceMessage : public OrthancStone::OriginMessage<SliceViewerWidget> { ORTHANC_STONE_MESSAGE(__FILE__, __LINE__); private: - const Slice& slice_; + const Deprecated::Slice& slice_; public: DisplayedSliceMessage(SliceViewerWidget& origin, - const Slice& slice) : + const Deprecated::Slice& slice) : OriginMessage(origin), slice_(slice) { } - const Slice& GetSlice() const + const Deprecated::Slice& GetSlice() const { return slice_; } @@ -74,7 +74,7 @@ LayersIndex layersIndex_; std::vector<IVolumeSlicer*> layers_; std::vector<RenderStyle> styles_; - CoordinateSystem3D plane_; + OrthancStone::CoordinateSystem3D plane_; std::auto_ptr<Scene> currentScene_; std::auto_ptr<Scene> pendingScene_; std::vector<bool> changedLayers_; @@ -82,7 +82,7 @@ bool LookupLayer(size_t& index /* out */, const IVolumeSlicer& layer) const; - void GetLayerExtent(Extent2D& extent, + void GetLayerExtent(OrthancStone::Extent2D& extent, IVolumeSlicer& source) const; void OnGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message); @@ -100,20 +100,20 @@ void ResetChangedLayers(); public: - SliceViewerWidget(MessageBroker& broker, + SliceViewerWidget(OrthancStone::MessageBroker& broker, const std::string& name); - virtual Extent2D GetSceneExtent(); + virtual OrthancStone::Extent2D GetSceneExtent(); protected: - virtual bool RenderScene(CairoContext& context, + virtual bool RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view); void ResetPendingScene(); void UpdateLayer(size_t index, ILayerRenderer* renderer, - const CoordinateSystem3D& plane); + const OrthancStone::CoordinateSystem3D& plane); void InvalidateAllLayers(); @@ -138,9 +138,9 @@ void SetLayerStyle(size_t layer, const RenderStyle& style); - void SetSlice(const CoordinateSystem3D& plane); + void SetSlice(const OrthancStone::CoordinateSystem3D& plane); - const CoordinateSystem3D& GetSlice() const + const OrthancStone::CoordinateSystem3D& GetSlice() const { return plane_; }
--- a/Framework/Widgets/TestCairoWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/TestCairoWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <stdio.h> -namespace OrthancStone +namespace Deprecated { namespace Samples { @@ -40,7 +40,7 @@ } - bool TestCairoWidget::RenderCairo(CairoContext& context) + bool TestCairoWidget::RenderCairo(OrthancStone::CairoContext& context) { cairo_t* cr = context.GetObject(); @@ -60,7 +60,7 @@ } - void TestCairoWidget::RenderMouseOverCairo(CairoContext& context, + void TestCairoWidget::RenderMouseOverCairo(OrthancStone::CairoContext& context, int x, int y) { @@ -96,10 +96,10 @@ } - IMouseTracker* TestCairoWidget::CreateMouseTracker(MouseButton button, + IMouseTracker* TestCairoWidget::CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) { UpdateStatusBar("Click"); @@ -107,18 +107,18 @@ } - void TestCairoWidget::MouseWheel(MouseWheelDirection direction, + void TestCairoWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { - UpdateStatusBar(direction == MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); + UpdateStatusBar(direction == OrthancStone::MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); } - void TestCairoWidget::KeyPressed(KeyboardKeys key, + void TestCairoWidget::KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { UpdateStatusBar("Key pressed: \"" + std::string(1, keyChar) + "\""); }
--- a/Framework/Widgets/TestCairoWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/TestCairoWidget.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "CairoWidget.h" -namespace OrthancStone +namespace Deprecated { namespace Samples { @@ -36,9 +36,9 @@ bool animate_; protected: - virtual bool RenderCairo(CairoContext& context); + virtual bool RenderCairo(OrthancStone::CairoContext& context); - virtual void RenderMouseOverCairo(CairoContext& context, + virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, int x, int y); @@ -48,20 +48,20 @@ virtual void SetSize(unsigned int width, unsigned int height); - virtual IMouseTracker* CreateMouseTracker(MouseButton button, + virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches); - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); virtual bool HasAnimation() const {
--- a/Framework/Widgets/TestWorldSceneWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/TestWorldSceneWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include <math.h> #include <stdio.h> -namespace OrthancStone +namespace Deprecated { namespace Samples { @@ -35,8 +35,8 @@ public: virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, + OrthancStone::MouseButton button, + OrthancStone::KeyboardModifiers modifiers, int viewportX, int viewportY, double x, @@ -54,7 +54,7 @@ return NULL; } - virtual void MouseOver(CairoContext& context, + virtual void MouseOver(OrthancStone::CairoContext& context, WorldSceneWidget& widget, const ViewportGeometry& view, double x, @@ -75,20 +75,20 @@ } virtual void MouseWheel(WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, + OrthancStone::MouseWheelDirection direction, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) { if (statusBar) { - statusBar->SetMessage(direction == MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); + statusBar->SetMessage(direction == OrthancStone::MouseWheelDirection_Down ? "Wheel down" : "Wheel up"); } } virtual void KeyPressed(WorldSceneWidget& widget, - KeyboardKeys key, + OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) { if (statusBar) @@ -99,7 +99,7 @@ }; - bool TestWorldSceneWidget::RenderScene(CairoContext& context, + bool TestWorldSceneWidget::RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view) { cairo_t* cr = context.GetObject(); @@ -127,9 +127,9 @@ } - Extent2D TestWorldSceneWidget::GetSceneExtent() + OrthancStone::Extent2D TestWorldSceneWidget::GetSceneExtent() { - return Extent2D(-10, -.5, 10, .5); + return OrthancStone::Extent2D(-10, -.5, 10, .5); }
--- a/Framework/Widgets/TestWorldSceneWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/TestWorldSceneWidget.h Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <memory> -namespace OrthancStone +namespace Deprecated { namespace Samples { @@ -39,13 +39,13 @@ unsigned int count_; protected: - virtual bool RenderScene(CairoContext& context, + virtual bool RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view); public: TestWorldSceneWidget(const std::string& name, bool animate); - virtual Extent2D GetSceneExtent(); + virtual OrthancStone::Extent2D GetSceneExtent(); virtual bool HasAnimation() const {
--- a/Framework/Widgets/WidgetBase.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/WidgetBase.cpp Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <Core/Images/ImageProcessing.h> #include <Core/Logging.h> -namespace OrthancStone +namespace Deprecated { void WidgetBase::NotifyContentChanged() { @@ -69,7 +69,7 @@ } - void WidgetBase::ClearBackgroundCairo(CairoContext& context) const + void WidgetBase::ClearBackgroundCairo(OrthancStone::CairoContext& context) const { // Clear the background using Cairo @@ -86,8 +86,8 @@ void WidgetBase::ClearBackgroundCairo(Orthanc::ImageAccessor& target) const { - CairoSurface surface(target, false /* no alpha */); - CairoContext context(surface); + OrthancStone::CairoSurface surface(target, false /* no alpha */); + OrthancStone::CairoContext context(surface); ClearBackgroundCairo(context); }
--- a/Framework/Widgets/WidgetBase.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/WidgetBase.h Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include "../Viewport/CairoContext.h" #include "../Viewport/WidgetViewport.h" -namespace OrthancStone +namespace Deprecated { class WidgetBase : public IWidget { @@ -42,7 +42,7 @@ protected: void ClearBackgroundOrthanc(Orthanc::ImageAccessor& target) const; - void ClearBackgroundCairo(CairoContext& context) const; + void ClearBackgroundCairo(OrthancStone::CairoContext& context) const; void ClearBackgroundCairo(Orthanc::ImageAccessor& target) const;
--- a/Framework/Widgets/WorldSceneWidget.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/WorldSceneWidget.cpp Tue May 21 13:25:58 2019 +0200 @@ -32,7 +32,7 @@ #include <memory> #include <cassert> -namespace OrthancStone +namespace Deprecated { // this is an adapter between a IWorldSceneMouseTracker // that is tracking a mouse in scene coordinates/mm and @@ -60,8 +60,8 @@ { if (tracker_->HasRender()) { - CairoSurface surface(target, false /* no alpha */); - CairoContext context(surface); + OrthancStone::CairoSurface surface(target, false /* no alpha */); + OrthancStone::CairoContext context(surface); view_.ApplyTransform(context); tracker_->Render(context, view_.GetZoom()); } @@ -83,22 +83,26 @@ for (size_t t = 0; t < displayTouches.size(); t++) { double sx, sy; - view_.MapPixelCenterToScene(sx, sy, (int)displayTouches[t].x, (int)displayTouches[t].y); - sceneTouches.push_back(Touch(sx, sy)); + + view_.MapPixelCenterToScene( + sx, sy, (int)displayTouches[t].x, (int)displayTouches[t].y); + + sceneTouches.push_back( + Touch(static_cast<float>(sx), static_cast<float>(sy))); } tracker_->MouseMove(x, y, sceneX, sceneY, displayTouches, sceneTouches); } }; - bool WorldSceneWidget::RenderCairo(CairoContext& context) + bool WorldSceneWidget::RenderCairo(OrthancStone::CairoContext& context) { view_.ApplyTransform(context); return RenderScene(context, view_); } - void WorldSceneWidget::RenderMouseOverCairo(CairoContext& context, + void WorldSceneWidget::RenderMouseOverCairo(OrthancStone::CairoContext& context, int x, int y) { @@ -152,10 +156,10 @@ } - IMouseTracker* WorldSceneWidget::CreateMouseTracker(MouseButton button, + IMouseTracker* WorldSceneWidget::CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches) { double sceneX, sceneY; @@ -185,10 +189,10 @@ { switch (button) { - case MouseButton_Middle: + case OrthancStone::MouseButton_Middle: return new SceneMouseTracker(view_, new PanMouseTracker(*this, x, y)); - case MouseButton_Right: + case OrthancStone::MouseButton_Right: return new SceneMouseTracker(view_, new ZoomMouseTracker(*this, x, y)); default: @@ -203,10 +207,10 @@ } - void WorldSceneWidget::MouseWheel(MouseWheelDirection direction, + void WorldSceneWidget::MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { if (interactor_) { @@ -215,9 +219,9 @@ } - void WorldSceneWidget::KeyPressed(KeyboardKeys key, + void WorldSceneWidget::KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers) + OrthancStone::KeyboardModifiers modifiers) { if (interactor_) {
--- a/Framework/Widgets/WorldSceneWidget.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/WorldSceneWidget.h Tue May 21 13:25:58 2019 +0200 @@ -26,7 +26,7 @@ #include "../Toolbox/ViewportGeometry.h" -namespace OrthancStone +namespace Deprecated { class WorldSceneWidget : public CairoWidget { @@ -38,16 +38,16 @@ bool hasDefaultMouseEvents_; protected: - virtual Extent2D GetSceneExtent() = 0; + virtual OrthancStone::Extent2D GetSceneExtent() = 0; - virtual bool RenderScene(CairoContext& context, + virtual bool RenderScene(OrthancStone::CairoContext& context, const ViewportGeometry& view) = 0; // From CairoWidget - virtual bool RenderCairo(CairoContext& context); + virtual bool RenderCairo(OrthancStone::CairoContext& context); // From CairoWidget - virtual void RenderMouseOverCairo(CairoContext& context, + virtual void RenderMouseOverCairo(OrthancStone::CairoContext& context, int x, int y); @@ -85,19 +85,19 @@ virtual void FitContent(); - virtual IMouseTracker* CreateMouseTracker(MouseButton button, + virtual IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button, int x, int y, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, const std::vector<Touch>& touches); - virtual void MouseWheel(MouseWheelDirection direction, + virtual void MouseWheel(OrthancStone::MouseWheelDirection direction, int x, int y, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); - virtual void KeyPressed(KeyboardKeys key, + virtual void KeyPressed(OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers); + OrthancStone::KeyboardModifiers modifiers); }; }
--- a/Framework/Widgets/ZoomMouseTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/ZoomMouseTracker.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,7 +24,7 @@ #include <Core/Logging.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { ZoomMouseTracker::ZoomMouseTracker(WorldSceneWidget& that, int x, @@ -51,7 +51,7 @@ } - void ZoomMouseTracker::Render(CairoContext& context, + void ZoomMouseTracker::Render(OrthancStone::CairoContext& context, double zoom) { throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
--- a/Framework/Widgets/ZoomMouseTracker.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/Widgets/ZoomMouseTracker.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "WorldSceneWidget.h" -namespace OrthancStone +namespace Deprecated { class ZoomMouseTracker : public IWorldSceneMouseTracker { @@ -51,7 +51,7 @@ { } - virtual void Render(CairoContext& context, + virtual void Render(OrthancStone::CairoContext& context, double zoom); virtual void MouseMove(int displayX,
--- a/Framework/dev.h Thu May 16 19:10:38 2019 +0200 +++ b/Framework/dev.h Tue May 21 13:25:58 2019 +0200 @@ -38,16 +38,16 @@ #include <boost/math/special_functions/round.hpp> -namespace OrthancStone +namespace Deprecated { // TODO: Handle errors while loading class OrthancVolumeImage : public ISlicedVolume, - public IObserver + public OrthancStone::IObserver { private: OrthancSlicesLoader loader_; - std::auto_ptr<ImageBuffer3D> image_; + std::auto_ptr<OrthancStone::ImageBuffer3D> image_; std::auto_ptr<DownloadStack> downloadStack_; bool computeRange_; size_t pendingSlices_; @@ -59,7 +59,7 @@ unsigned int slice; if (downloadStack_->Pop(slice)) { - loader_.ScheduleLoadSliceImage(slice, SliceImageQuality_Jpeg90); + loader_.ScheduleLoadSliceImage(slice, OrthancStone::SliceImageQuality_Jpeg90); } } @@ -67,8 +67,8 @@ static bool IsCompatible(const Slice& a, const Slice& b) { - if (!GeometryToolbox::IsParallel(a.GetGeometry().GetNormal(), - b.GetGeometry().GetNormal())) + if (!OrthancStone::GeometryToolbox::IsParallel(a.GetGeometry().GetNormal(), + b.GetGeometry().GetNormal())) { LOG(ERROR) << "A slice in the volume image is not parallel to the others."; return false; @@ -87,8 +87,8 @@ return false; } - if (!LinearAlgebra::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || - !LinearAlgebra::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) + if (!OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || + !OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) { LOG(ERROR) << "The pixel spacing of the slices change across the volume image"; return false; @@ -141,8 +141,8 @@ for (size_t i = 1; i < loader_.GetSlicesCount(); i++) { - if (!LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)), - 0.001 /* this is expressed in mm */)) + if (!OrthancStone::LinearAlgebra::IsNear(spacingZ, GetDistance(loader_.GetSlice(i - 1), loader_.GetSlice(i)), + 0.001 /* this is expressed in mm */)) { LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; BroadcastMessage(ISlicedVolume::GeometryErrorMessage(*this)); @@ -156,10 +156,10 @@ LOG(INFO) << "Creating a volume image of size " << width << "x" << height << "x" << loader_.GetSlicesCount() << " in " << Orthanc::EnumerationToString(format); - image_.reset(new ImageBuffer3D(format, width, height, static_cast<unsigned int>(loader_.GetSlicesCount()), computeRange_)); - image_->SetAxialGeometry(loader_.GetSlice(0).GetGeometry()); - image_->SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(), - loader_.GetSlice(0).GetPixelSpacingY(), spacingZ); + image_.reset(new OrthancStone::ImageBuffer3D(format, width, height, static_cast<unsigned int>(loader_.GetSlicesCount()), computeRange_)); + image_->GetGeometry().SetAxialGeometry(loader_.GetSlice(0).GetGeometry()); + image_->GetGeometry().SetVoxelDimensions(loader_.GetSlice(0).GetPixelSpacingX(), + loader_.GetSlice(0).GetPixelSpacingY(), spacingZ); image_->Clear(); downloadStack_.reset(new DownloadStack(static_cast<unsigned int>(loader_.GetSlicesCount()))); @@ -190,12 +190,12 @@ assert(&message.GetOrigin() == &loader_); { - ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, message.GetSliceIndex()); + OrthancStone::ImageBuffer3D::SliceWriter writer(*image_, OrthancStone::VolumeProjection_Axial, message.GetSliceIndex()); Orthanc::ImageProcessing::Copy(writer.GetAccessor(), message.GetImage()); } BroadcastMessage(ISlicedVolume::SliceContentChangedMessage - (*this, message.GetSliceIndex(), message.GetSlice())); + (*this, message.GetSliceIndex(), message.GetSlice())); if (pendingSlices_ == 1) { @@ -221,7 +221,7 @@ public: - OrthancVolumeImage(MessageBroker& broker, + OrthancVolumeImage(OrthancStone::MessageBroker& broker, OrthancApiClient& orthanc, bool computeRange) : ISlicedVolume(broker), @@ -231,19 +231,19 @@ pendingSlices_(0) { loader_.RegisterObserverCallback( - new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryReadyMessage> + new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryReadyMessage> (*this, &OrthancVolumeImage::OnSliceGeometryReady)); loader_.RegisterObserverCallback( - new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryErrorMessage> + new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceGeometryErrorMessage> (*this, &OrthancVolumeImage::OnSliceGeometryError)); loader_.RegisterObserverCallback( - new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageReadyMessage> + new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageReadyMessage> (*this, &OrthancVolumeImage::OnSliceImageReady)); loader_.RegisterObserverCallback( - new Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageErrorMessage> + new OrthancStone::Callable<OrthancVolumeImage, OrthancSlicesLoader::SliceImageErrorMessage> (*this, &OrthancVolumeImage::OnSliceImageError)); } @@ -273,7 +273,7 @@ return loader_.GetSlice(index); } - ImageBuffer3D& GetImage() const + OrthancStone::ImageBuffer3D& GetImage() const { if (image_.get() == NULL) { @@ -310,7 +310,7 @@ double pixelSpacingX_; double pixelSpacingY_; double sliceThickness_; - CoordinateSystem3D reference_; + OrthancStone::CoordinateSystem3D reference_; DicomFrameConverter converter_; double ComputeAxialThickness(const OrthancVolumeImage& volume) const @@ -371,13 +371,13 @@ pixelSpacingY_ = axialThickness; sliceThickness_ = axial.GetPixelSpacingY(); - Vector origin = axial.GetGeometry().GetOrigin(); + OrthancStone::Vector origin = axial.GetGeometry().GetOrigin(); origin += (static_cast<double>(volume.GetSlicesCount() - 1) * - axialThickness * axial.GetGeometry().GetNormal()); + axialThickness * axial.GetGeometry().GetNormal()); - reference_ = CoordinateSystem3D(origin, - axial.GetGeometry().GetAxisX(), - - axial.GetGeometry().GetNormal()); + reference_ = OrthancStone::CoordinateSystem3D(origin, + axial.GetGeometry().GetAxisX(), + - axial.GetGeometry().GetNormal()); } void SetupSagittal(const OrthancVolumeImage& volume) @@ -393,18 +393,18 @@ pixelSpacingY_ = axialThickness; sliceThickness_ = axial.GetPixelSpacingX(); - Vector origin = axial.GetGeometry().GetOrigin(); + OrthancStone::Vector origin = axial.GetGeometry().GetOrigin(); origin += (static_cast<double>(volume.GetSlicesCount() - 1) * - axialThickness * axial.GetGeometry().GetNormal()); + axialThickness * axial.GetGeometry().GetNormal()); - reference_ = CoordinateSystem3D(origin, - axial.GetGeometry().GetAxisY(), - axial.GetGeometry().GetNormal()); + reference_ = OrthancStone::CoordinateSystem3D(origin, + axial.GetGeometry().GetAxisY(), + axial.GetGeometry().GetNormal()); } public: VolumeImageGeometry(const OrthancVolumeImage& volume, - VolumeProjection projection) + OrthancStone::VolumeProjection projection) { if (volume.GetSlicesCount() == 0) { @@ -415,20 +415,20 @@ switch (projection) { - case VolumeProjection_Axial: - SetupAxial(volume); - break; + case OrthancStone::VolumeProjection_Axial: + SetupAxial(volume); + break; - case VolumeProjection_Coronal: - SetupCoronal(volume); - break; + case OrthancStone::VolumeProjection_Coronal: + SetupCoronal(volume); + break; - case VolumeProjection_Sagittal: - SetupSagittal(volume); - break; + case OrthancStone::VolumeProjection_Sagittal: + SetupSagittal(volume); + break; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } } @@ -437,18 +437,18 @@ return depth_; } - const Vector& GetNormal() const + const OrthancStone::Vector& GetNormal() const { return reference_.GetNormal(); } bool LookupSlice(size_t& index, - const CoordinateSystem3D& slice) const + const OrthancStone::CoordinateSystem3D& slice) const { bool opposite; - if (!GeometryToolbox::IsParallelOrOpposite(opposite, - reference_.GetNormal(), - slice.GetNormal())) + if (!OrthancStone::GeometryToolbox::IsParallelOrOpposite(opposite, + reference_.GetNormal(), + slice.GetNormal())) { return false; } @@ -459,7 +459,7 @@ int s = static_cast<int>(boost::math::iround(z)); if (s < 0 || - s >= static_cast<int>(depth_)) + s >= static_cast<int>(depth_)) { return false; } @@ -478,10 +478,10 @@ } else { - CoordinateSystem3D origin(reference_.GetOrigin() + - static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), - reference_.GetAxisX(), - reference_.GetAxisY()); + OrthancStone::CoordinateSystem3D origin(reference_.GetOrigin() + + static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), + reference_.GetAxisX(), + reference_.GetAxisY()); return new Slice(origin, pixelSpacingX_, pixelSpacingY_, sliceThickness_, width_, height_, converter_); @@ -493,7 +493,7 @@ class VolumeImageMPRSlicer : public IVolumeSlicer, - public IObserver + public OrthancStone::IObserver { private: class RendererFactory : public LayerReadyMessage::IRendererFactory @@ -507,9 +507,9 @@ RendererFactory(const Orthanc::ImageAccessor& frame, const Slice& slice, bool isFullQuality) : - frame_(frame), - slice_(slice), - isFullQuality_(isFullQuality) + frame_(frame), + slice_(slice), + isFullQuality_(isFullQuality) { } @@ -536,9 +536,9 @@ assert(&message.GetOrigin() == &volume_); // These 3 values are only used to speed up the IVolumeSlicer - axialGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Axial)); - coronalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Coronal)); - sagittalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Sagittal)); + axialGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Axial)); + coronalGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Coronal)); + sagittalGeometry_.reset(new VolumeImageGeometry(volume_, OrthancStone::VolumeProjection_Sagittal)); BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*this)); } @@ -567,7 +567,7 @@ BroadcastMessage(IVolumeSlicer::ContentChangedMessage(*this)); } - const VolumeImageGeometry& GetProjectionGeometry(VolumeProjection projection) + const VolumeImageGeometry& GetProjectionGeometry(OrthancStone::VolumeProjection projection) { if (!IsGeometryReady()) { @@ -576,45 +576,45 @@ switch (projection) { - case VolumeProjection_Axial: - return *axialGeometry_; + case OrthancStone::VolumeProjection_Axial: + return *axialGeometry_; - case VolumeProjection_Sagittal: - return *sagittalGeometry_; + case OrthancStone::VolumeProjection_Sagittal: + return *sagittalGeometry_; - case VolumeProjection_Coronal: - return *coronalGeometry_; + case OrthancStone::VolumeProjection_Coronal: + return *coronalGeometry_; - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } } - bool DetectProjection(VolumeProjection& projection, - const CoordinateSystem3D& viewportSlice) + bool DetectProjection(OrthancStone::VolumeProjection& projection, + const OrthancStone::CoordinateSystem3D& viewportSlice) { bool isOpposite; // Ignored - if (GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - axialGeometry_->GetNormal())) + if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, + viewportSlice.GetNormal(), + axialGeometry_->GetNormal())) { - projection = VolumeProjection_Axial; + projection = OrthancStone::VolumeProjection_Axial; return true; } - else if (GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - sagittalGeometry_->GetNormal())) + else if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, + viewportSlice.GetNormal(), + sagittalGeometry_->GetNormal())) { - projection = VolumeProjection_Sagittal; + projection = OrthancStone::VolumeProjection_Sagittal; return true; } - else if (GeometryToolbox::IsParallelOrOpposite(isOpposite, - viewportSlice.GetNormal(), - coronalGeometry_->GetNormal())) + else if (OrthancStone::GeometryToolbox::IsParallelOrOpposite(isOpposite, + viewportSlice.GetNormal(), + coronalGeometry_->GetNormal())) { - projection = VolumeProjection_Coronal; + projection = OrthancStone::VolumeProjection_Coronal; return true; } else @@ -625,33 +625,33 @@ public: - VolumeImageMPRSlicer(MessageBroker& broker, + VolumeImageMPRSlicer(OrthancStone::MessageBroker& broker, OrthancVolumeImage& volume) : - IVolumeSlicer(broker), - IObserver(broker), - volume_(volume) + IVolumeSlicer(broker), + IObserver(broker), + volume_(volume) { volume_.RegisterObserverCallback( - new Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryReadyMessage> + new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryReadyMessage> (*this, &VolumeImageMPRSlicer::OnGeometryReady)); volume_.RegisterObserverCallback( - new Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryErrorMessage> + new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::GeometryErrorMessage> (*this, &VolumeImageMPRSlicer::OnGeometryError)); volume_.RegisterObserverCallback( - new Callable<VolumeImageMPRSlicer, ISlicedVolume::ContentChangedMessage> + new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::ContentChangedMessage> (*this, &VolumeImageMPRSlicer::OnContentChanged)); volume_.RegisterObserverCallback( - new Callable<VolumeImageMPRSlicer, ISlicedVolume::SliceContentChangedMessage> + new OrthancStone::Callable<VolumeImageMPRSlicer, ISlicedVolume::SliceContentChangedMessage> (*this, &VolumeImageMPRSlicer::OnSliceContentChanged)); } - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE { - VolumeProjection projection; + OrthancStone::VolumeProjection projection; if (!IsGeometryReady() || !DetectProjection(projection, viewportSlice)) @@ -669,9 +669,9 @@ } } - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) ORTHANC_OVERRIDE { - VolumeProjection projection; + OrthancStone::VolumeProjection projection; if (IsGeometryReady() && DetectProjection(projection, viewportSlice)) @@ -687,7 +687,7 @@ std::auto_ptr<Orthanc::Image> frame; { - ImageBuffer3D::SliceReader reader(volume_.GetImage(), projection, static_cast<unsigned int>(closest)); + OrthancStone::ImageBuffer3D::SliceReader reader(volume_.GetImage(), projection, static_cast<unsigned int>(closest)); // TODO Transfer ownership if non-axial, to avoid memcpy frame.reset(Orthanc::Image::Clone(reader.GetAccessor())); @@ -703,7 +703,7 @@ } // Error - CoordinateSystem3D slice; + OrthancStone::CoordinateSystem3D slice; BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, slice)); } }; @@ -711,11 +711,11 @@ class VolumeImageInteractor : public IWorldSceneInteractor, - public IObserver + public OrthancStone::IObserver { private: SliceViewerWidget& widget_; - VolumeProjection projection_; + OrthancStone::VolumeProjection projection_; std::auto_ptr<VolumeImageGeometry> slices_; size_t slice_; @@ -736,8 +736,8 @@ virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, const ViewportGeometry& view, - MouseButton button, - KeyboardModifiers modifiers, + OrthancStone::MouseButton button, + OrthancStone::KeyboardModifiers modifiers, int viewportX, int viewportY, double x, @@ -748,7 +748,7 @@ return NULL; } - virtual void MouseOver(CairoContext& context, + virtual void MouseOver(OrthancStone::CairoContext& context, WorldSceneWidget& widget, const ViewportGeometry& view, double x, @@ -758,57 +758,57 @@ } virtual void MouseWheel(WorldSceneWidget& widget, - MouseWheelDirection direction, - KeyboardModifiers modifiers, + OrthancStone::MouseWheelDirection direction, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) ORTHANC_OVERRIDE { - int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); + int scale = (modifiers & OrthancStone::KeyboardModifiers_Control ? 10 : 1); switch (direction) { - case MouseWheelDirection_Up: - OffsetSlice(-scale); - break; + case OrthancStone::MouseWheelDirection_Up: + OffsetSlice(-scale); + break; - case MouseWheelDirection_Down: - OffsetSlice(scale); - break; + case OrthancStone::MouseWheelDirection_Down: + OffsetSlice(scale); + break; - default: - break; + default: + break; } } virtual void KeyPressed(WorldSceneWidget& widget, - KeyboardKeys key, + OrthancStone::KeyboardKeys key, char keyChar, - KeyboardModifiers modifiers, + OrthancStone::KeyboardModifiers modifiers, IStatusBar* statusBar) ORTHANC_OVERRIDE { switch (keyChar) { - case 's': - widget.FitContent(); - break; + case 's': + widget.FitContent(); + break; - default: - break; + default: + break; } } public: - VolumeImageInteractor(MessageBroker& broker, + VolumeImageInteractor(OrthancStone::MessageBroker& broker, OrthancVolumeImage& volume, SliceViewerWidget& widget, - VolumeProjection projection) : - IObserver(broker), - widget_(widget), - projection_(projection) + OrthancStone::VolumeProjection projection) : + IObserver(broker), + widget_(widget), + projection_(projection) { widget.SetInteractor(*this); volume.RegisterObserverCallback( - new Callable<VolumeImageInteractor, ISlicedVolume::GeometryReadyMessage> + new OrthancStone::Callable<VolumeImageInteractor, ISlicedVolume::GeometryReadyMessage> (*this, &VolumeImageInteractor::OnGeometryReady)); } @@ -876,14 +876,14 @@ double y1_; double x2_; double y2_; - const CoordinateSystem3D& slice_; + const OrthancStone::CoordinateSystem3D& slice_; public: RendererFactory(double x1, double y1, double x2, double y2, - const CoordinateSystem3D& slice) : + const OrthancStone::CoordinateSystem3D& slice) : x1_(x1), y1_(y1), x2_(x2), @@ -901,7 +901,7 @@ SliceViewerWidget& otherPlane_; public: - ReferenceLineSource(MessageBroker& broker, + ReferenceLineSource(OrthancStone::MessageBroker& broker, SliceViewerWidget& otherPlane) : IVolumeSlicer(broker), otherPlane_(otherPlane) @@ -909,24 +909,24 @@ BroadcastMessage(IVolumeSlicer::GeometryReadyMessage(*this)); } - virtual bool GetExtent(std::vector<Vector>& points, - const CoordinateSystem3D& viewportSlice) + virtual bool GetExtent(std::vector<OrthancStone::Vector>& points, + const OrthancStone::CoordinateSystem3D& viewportSlice) { return false; } - virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) + virtual void ScheduleLayerCreation(const OrthancStone::CoordinateSystem3D& viewportSlice) { Slice reference(viewportSlice, 0.001); - Vector p, d; + OrthancStone::Vector p, d; - const CoordinateSystem3D& slice = otherPlane_.GetSlice(); + const OrthancStone::CoordinateSystem3D& slice = otherPlane_.GetSlice(); // Compute the line of intersection between the two slices - if (!GeometryToolbox::IntersectTwoPlanes(p, d, - slice.GetOrigin(), slice.GetNormal(), - viewportSlice.GetOrigin(), viewportSlice.GetNormal())) + if (!OrthancStone::GeometryToolbox::IntersectTwoPlanes(p, d, + slice.GetOrigin(), slice.GetNormal(), + viewportSlice.GetOrigin(), viewportSlice.GetNormal())) { // The two slice are parallel, don't try and display the intersection BroadcastMessage(IVolumeSlicer::LayerErrorMessage(*this, reference.GetGeometry())); @@ -937,12 +937,12 @@ viewportSlice.ProjectPoint(x1, y1, p); viewportSlice.ProjectPoint(x2, y2, p + 1000.0 * d); - const Extent2D extent = otherPlane_.GetSceneExtent(); + const OrthancStone::Extent2D extent = otherPlane_.GetSceneExtent(); - if (GeometryToolbox::ClipLineToRectangle(x1, y1, x2, y2, - x1, y1, x2, y2, - extent.GetX1(), extent.GetY1(), - extent.GetX2(), extent.GetY2())) + if (OrthancStone::GeometryToolbox::ClipLineToRectangle(x1, y1, x2, y2, + x1, y1, x2, y2, + extent.GetX1(), extent.GetY1(), + extent.GetX2(), extent.GetY2())) { RendererFactory factory(x1, y1, x2, y2, slice); BroadcastMessage(IVolumeSlicer::LayerReadyMessage(*this, factory, reference.GetGeometry()));
--- a/Platforms/Generic/DelayedCallCommand.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/DelayedCallCommand.cpp Tue May 21 13:25:58 2019 +0200 @@ -24,13 +24,13 @@ #include <iostream> -namespace OrthancStone +namespace Deprecated { - DelayedCallCommand::DelayedCallCommand(MessageBroker& broker, - MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership + DelayedCallCommand::DelayedCallCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership unsigned int timeoutInMs, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context + OrthancStone::NativeStoneApplicationContext& context ) : IObservable(broker), callback_(callback), @@ -55,7 +55,7 @@ // We want to make sure that, i.e, the UpdateThread is not // triggered while we are updating the "model" with the result of // an OracleCommand - NativeStoneApplicationContext::GlobalMutexLocker lock(context_); + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); if (callback_.get() != NULL) {
--- a/Platforms/Generic/DelayedCallCommand.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/DelayedCallCommand.h Tue May 21 13:25:58 2019 +0200 @@ -30,23 +30,23 @@ #include <boost/date_time/posix_time/posix_time.hpp> -namespace OrthancStone +namespace Deprecated { - class DelayedCallCommand : public IOracleCommand, IObservable + class DelayedCallCommand : public IOracleCommand, OrthancStone::IObservable { protected: - std::auto_ptr<MessageHandler<IDelayedCallExecutor::TimeoutMessage> > callback_; + std::auto_ptr<OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage> > callback_; std::auto_ptr<Orthanc::IDynamicObject> payload_; - NativeStoneApplicationContext& context_; + OrthancStone::NativeStoneApplicationContext& context_; boost::posix_time::ptime expirationTimePoint_; unsigned int timeoutInMs_; public: - DelayedCallCommand(MessageBroker& broker, - MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership + DelayedCallCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, // takes ownership unsigned int timeoutInMs, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context + OrthancStone::NativeStoneApplicationContext& context ); virtual void Execute();
--- a/Platforms/Generic/IOracleCommand.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/IOracleCommand.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include <Core/IDynamicObject.h> -namespace OrthancStone +namespace Deprecated { class IOracleCommand : public Orthanc::IDynamicObject {
--- a/Platforms/Generic/Oracle.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/Oracle.cpp Tue May 21 13:25:58 2019 +0200 @@ -29,7 +29,7 @@ #include <stdio.h> #include <boost/thread/mutex.hpp> -namespace OrthancStone +namespace Deprecated { class Oracle::PImpl {
--- a/Platforms/Generic/Oracle.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/Oracle.h Tue May 21 13:25:58 2019 +0200 @@ -25,7 +25,7 @@ #include <boost/shared_ptr.hpp> -namespace OrthancStone +namespace Deprecated { class Oracle : public boost::noncopyable {
--- a/Platforms/Generic/OracleDelayedCallExecutor.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/OracleDelayedCallExecutor.h Tue May 21 13:25:58 2019 +0200 @@ -26,26 +26,26 @@ #include "../../Applications/Generic/NativeStoneApplicationContext.h" #include "DelayedCallCommand.h" -namespace OrthancStone +namespace Deprecated { // The OracleTimeout executes callbacks after a delay. class OracleDelayedCallExecutor : public IDelayedCallExecutor { private: Oracle& oracle_; - NativeStoneApplicationContext& context_; + OrthancStone::NativeStoneApplicationContext& context_; public: - OracleDelayedCallExecutor(MessageBroker& broker, + OracleDelayedCallExecutor(OrthancStone::MessageBroker& broker, Oracle& oracle, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : IDelayedCallExecutor(broker), oracle_(oracle), context_(context) { } - virtual void Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, + virtual void Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, unsigned int timeoutInMs = 1000) { oracle_.Submit(new DelayedCallCommand(broker_, callback, timeoutInMs, NULL, context_));
--- a/Platforms/Generic/OracleWebService.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/OracleWebService.cpp Tue May 21 13:25:58 2019 +0200 @@ -22,24 +22,24 @@ #include "OracleWebService.h" #include "../../Framework/Toolbox/IWebService.h" -namespace OrthancStone +namespace Deprecated { - class OracleWebService::WebServiceCachedGetCommand : public IOracleCommand, IObservable + class OracleWebService::WebServiceCachedGetCommand : public IOracleCommand, OrthancStone::IObservable { protected: - std::auto_ptr<MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; + std::auto_ptr<OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; std::auto_ptr<Orthanc::IDynamicObject> payload_; boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage_; - NativeStoneApplicationContext& context_; + OrthancStone::NativeStoneApplicationContext& context_; public: - WebServiceCachedGetCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + WebServiceCachedGetCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context + OrthancStone::NativeStoneApplicationContext& context ) : IObservable(broker), successCallback_(successCallback), @@ -59,7 +59,7 @@ // We want to make sure that, i.e, the UpdateThread is not // triggered while we are updating the "model" with the result of // a WebServiceCommand - NativeStoneApplicationContext::GlobalMutexLocker lock(context_); + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); IWebService::HttpRequestSuccessMessage successMessage(cachedMessage_->GetUri(), cachedMessage_->GetAnswer(), @@ -73,7 +73,7 @@ void OracleWebService::NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) { oracle_.Submit(new WebServiceCachedGetCommand(GetBroker(), successCallback, cachedMessage, payload, context_)); }
--- a/Platforms/Generic/OracleWebService.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/OracleWebService.h Tue May 21 13:25:58 2019 +0200 @@ -28,7 +28,7 @@ #include "WebServiceDeleteCommand.h" #include "../../Applications/Generic/NativeStoneApplicationContext.h" -namespace OrthancStone +namespace Deprecated { // The OracleWebService performs HTTP requests in a native environment. // It uses a thread pool to handle multiple HTTP requests in a same time. @@ -37,16 +37,16 @@ { private: Oracle& oracle_; - NativeStoneApplicationContext& context_; + OrthancStone::NativeStoneApplicationContext& context_; Orthanc::WebServiceParameters parameters_; class WebServiceCachedGetCommand; public: - OracleWebService(MessageBroker& broker, + OracleWebService(OrthancStone::MessageBroker& broker, Oracle& oracle, const Orthanc::WebServiceParameters& parameters, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : BaseWebService(broker), oracle_(oracle), context_(context), @@ -58,8 +58,8 @@ const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, // takes ownership unsigned int timeoutInSeconds = 60) { oracle_.Submit(new WebServicePostCommand(GetBroker(), successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, body, payload, context_)); @@ -68,8 +68,8 @@ virtual void DeleteAsync(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL, unsigned int timeoutInSeconds = 60) { oracle_.Submit(new WebServiceDeleteCommand(GetBroker(), successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); @@ -79,8 +79,8 @@ virtual void GetAsyncInternal(const std::string& uri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,// takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback = NULL,// takes ownership unsigned int timeoutInSeconds = 60) { oracle_.Submit(new WebServiceGetCommand(GetBroker(), successCallback, failureCallback, parameters_, uri, headers, timeoutInSeconds, payload, context_)); @@ -88,7 +88,7 @@ virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback); + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback); }; }
--- a/Platforms/Generic/WebServiceCommandBase.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceCommandBase.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,17 +23,17 @@ #include <Core/HttpClient.h> -namespace OrthancStone +namespace Deprecated { - WebServiceCommandBase::WebServiceCommandBase(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, + WebServiceCommandBase::WebServiceCommandBase(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : IObservable(broker), successCallback_(successCallback), failureCallback_(failureCallback), @@ -52,7 +52,7 @@ // We want to make sure that, i.e, the UpdateThread is not // triggered while we are updating the "model" with the result of // a WebServiceCommand - NativeStoneApplicationContext::GlobalMutexLocker lock(context_); + OrthancStone::NativeStoneApplicationContext::GlobalMutexLocker lock(context_); if (success_ && successCallback_.get() != NULL) {
--- a/Platforms/Generic/WebServiceCommandBase.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceCommandBase.h Tue May 21 13:25:58 2019 +0200 @@ -32,13 +32,13 @@ #include <memory> -namespace OrthancStone +namespace Deprecated { - class WebServiceCommandBase : public IOracleCommand, IObservable + class WebServiceCommandBase : public IOracleCommand, OrthancStone::IObservable { protected: - std::auto_ptr<MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; - std::auto_ptr<MessageHandler<IWebService::HttpRequestErrorMessage> > failureCallback_; + std::auto_ptr<OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> > successCallback_; + std::auto_ptr<OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> > failureCallback_; Orthanc::WebServiceParameters parameters_; std::string url_; IWebService::HttpHeaders headers_; @@ -46,19 +46,19 @@ bool success_; std::string answer_; IWebService::HttpHeaders answerHeaders_; - NativeStoneApplicationContext& context_; + OrthancStone::NativeStoneApplicationContext& context_; unsigned int timeoutInSeconds_; public: - WebServiceCommandBase(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServiceCommandBase(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context + OrthancStone::NativeStoneApplicationContext& context ); virtual void Execute() = 0;
--- a/Platforms/Generic/WebServiceDeleteCommand.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceDeleteCommand.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,17 +23,17 @@ #include <Core/HttpClient.h> -namespace OrthancStone +namespace Deprecated { - WebServiceDeleteCommand::WebServiceDeleteCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServiceDeleteCommand::WebServiceDeleteCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, - const IWebService::HttpHeaders& headers, + const Deprecated::IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) { } @@ -45,7 +45,7 @@ client.SetTimeout(timeoutInSeconds_); client.SetMethod(Orthanc::HttpMethod_Delete); - for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + for (Deprecated::IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) { client.AddHeader(it->first, it->second); }
--- a/Platforms/Generic/WebServiceDeleteCommand.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceDeleteCommand.h Tue May 21 13:25:58 2019 +0200 @@ -23,20 +23,20 @@ #include "WebServiceCommandBase.h" -namespace OrthancStone +namespace Deprecated { class WebServiceDeleteCommand : public WebServiceCommandBase { public: - WebServiceDeleteCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServiceDeleteCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context); + OrthancStone::NativeStoneApplicationContext& context); virtual void Execute(); };
--- a/Platforms/Generic/WebServiceGetCommand.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceGetCommand.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,18 +23,18 @@ #include <Core/HttpClient.h> -namespace OrthancStone +namespace Deprecated { - WebServiceGetCommand::WebServiceGetCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServiceGetCommand::WebServiceGetCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) { }
--- a/Platforms/Generic/WebServiceGetCommand.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServiceGetCommand.h Tue May 21 13:25:58 2019 +0200 @@ -23,20 +23,20 @@ #include "WebServiceCommandBase.h" -namespace OrthancStone +namespace Deprecated { class WebServiceGetCommand : public WebServiceCommandBase { public: - WebServiceGetCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServiceGetCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context); + OrthancStone::NativeStoneApplicationContext& context); virtual void Execute(); };
--- a/Platforms/Generic/WebServicePostCommand.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServicePostCommand.cpp Tue May 21 13:25:58 2019 +0200 @@ -23,18 +23,18 @@ #include <Core/HttpClient.h> -namespace OrthancStone +namespace Deprecated { - WebServicePostCommand::WebServicePostCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServicePostCommand::WebServicePostCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, - const IWebService::HttpHeaders& headers, + const Deprecated::IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context) : + OrthancStone::NativeStoneApplicationContext& context) : WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context), body_(body) { @@ -48,7 +48,7 @@ client.SetMethod(Orthanc::HttpMethod_Post); client.GetBody().swap(body_); - for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + for (Deprecated::IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) { client.AddHeader(it->first, it->second); }
--- a/Platforms/Generic/WebServicePostCommand.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Generic/WebServicePostCommand.h Tue May 21 13:25:58 2019 +0200 @@ -23,7 +23,7 @@ #include "WebServiceCommandBase.h" -namespace OrthancStone +namespace Deprecated { class WebServicePostCommand : public WebServiceCommandBase { @@ -31,16 +31,16 @@ std::string body_; public: - WebServicePostCommand(MessageBroker& broker, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership + WebServicePostCommand(OrthancStone::MessageBroker& broker, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, const std::string& url, const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, - NativeStoneApplicationContext& context); + OrthancStone::NativeStoneApplicationContext& context); virtual void Execute(); };
--- a/Platforms/Wasm/Defaults.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/Defaults.cpp Tue May 21 13:25:58 2019 +0200 @@ -26,16 +26,16 @@ static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); static OrthancStone::StatusBar statusBar_; -static std::list<std::shared_ptr<OrthancStone::WidgetViewport>> viewports_; +static std::list<std::shared_ptr<Deprecated::WidgetViewport>> viewports_; -std::shared_ptr<OrthancStone::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { +std::shared_ptr<Deprecated::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { for (const auto& v : viewports_) { if (v.get() == viewport) { return v; } } assert(false); - return std::shared_ptr<OrthancStone::WidgetViewport>(); + return std::shared_ptr<Deprecated::WidgetViewport>(); } #ifdef __cplusplus @@ -47,7 +47,7 @@ // when WASM needs a C++ viewport ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { - std::shared_ptr<OrthancStone::WidgetViewport> viewport(new OrthancStone::WidgetViewport(broker)); + std::shared_ptr<Deprecated::WidgetViewport> viewport(new Deprecated::WidgetViewport(broker)); printf("viewport %x\n", (int)viewport.get()); viewports_.push_back(viewport); @@ -57,7 +57,7 @@ viewport->SetStatusBar(statusBar_); viewport->RegisterObserverCallback( - new Callable<ViewportContentChangedObserver, IViewport::ViewportChangedMessage> + new Callable<ViewportContentChangedObserver, Deprecated::IViewport::ViewportChangedMessage> (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); return viewport.get(); @@ -65,7 +65,7 @@ // when WASM does not need a viewport anymore, it should release it void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { - viewports_.remove_if([viewport](const std::shared_ptr<OrthancStone::WidgetViewport>& v) { return v.get() == viewport;}); + viewports_.remove_if([viewport](const std::shared_ptr<Deprecated::WidgetViewport>& v) { return v.get() == viewport;}); printf("There are now %lu viewports in C++\n", viewports_.size()); } @@ -76,8 +76,8 @@ application.reset(CreateUserApplication(broker)); applicationWasmAdapter.reset(CreateWasmApplicationAdapter(broker, application.get())); - WasmWebService::SetBroker(broker); - WasmDelayedCallExecutor::SetBroker(broker); + Deprecated::WasmWebService::SetBroker(broker); + Deprecated::WasmDelayedCallExecutor::SetBroker(broker); startupParametersBuilder.Clear(); } @@ -104,8 +104,8 @@ context.reset(new OrthancStone::StoneApplicationContext(broker)); context->SetOrthancBaseUrl(baseUri); printf("Base URL to Orthanc API: [%s]\n", baseUri); - context->SetWebService(OrthancStone::WasmWebService::GetInstance()); - context->SetDelayedCallExecutor(OrthancStone::WasmDelayedCallExecutor::GetInstance()); + context->SetWebService(Deprecated::WasmWebService::GetInstance()); + context->SetDelayedCallExecutor(Deprecated::WasmDelayedCallExecutor::GetInstance()); application->Initialize(context.get(), statusBar_, parameters); application->InitializeWasm(); @@ -208,7 +208,7 @@ return; // Unknown button } - viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None, std::vector<OrthancStone::Touch>()); + viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None, std::vector<Deprecated::Touch>()); } @@ -239,10 +239,10 @@ int x, int y) { - viewport->MouseMove(x, y, std::vector<OrthancStone::Touch>()); + viewport->MouseMove(x, y, std::vector<Deprecated::Touch>()); } - void GetTouchVector(std::vector<OrthancStone::Touch>& output, + void GetTouchVector(std::vector<Deprecated::Touch>& output, int touchCount, float x0, float y0, @@ -254,15 +254,15 @@ // TODO: it might be nice to try to pass all the x0,y0 coordinates as arrays but that's not so easy to pass array between JS and C++ if (touchCount > 0) { - output.push_back(OrthancStone::Touch(x0, y0)); + output.push_back(Deprecated::Touch(x0, y0)); } if (touchCount > 1) { - output.push_back(OrthancStone::Touch(x1, y1)); + output.push_back(Deprecated::Touch(x1, y1)); } if (touchCount > 2) { - output.push_back(OrthancStone::Touch(x2, y2)); + output.push_back(Deprecated::Touch(x2, y2)); } } @@ -278,7 +278,7 @@ { printf("touch start with %d touches\n", touchCount); - std::vector<OrthancStone::Touch> touches; + std::vector<Deprecated::Touch> touches; GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); viewport->TouchStart(touches); } @@ -294,7 +294,7 @@ { printf("touch move with %d touches\n", touchCount); - std::vector<OrthancStone::Touch> touches; + std::vector<Deprecated::Touch> touches; GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); viewport->TouchMove(touches); } @@ -310,7 +310,7 @@ { printf("touch end with %d touches remaining\n", touchCount); - std::vector<OrthancStone::Touch> touches; + std::vector<Deprecated::Touch> touches; GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); viewport->TouchEnd(touches); }
--- a/Platforms/Wasm/Defaults.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/Defaults.h Tue May 21 13:25:58 2019 +0200 @@ -8,7 +8,7 @@ #include <Applications/IStoneApplication.h> #include <Platforms/Wasm/WasmPlatformApplicationAdapter.h> -typedef OrthancStone::WidgetViewport* ViewportHandle; // the objects exchanged between JS and C++ +typedef Deprecated::WidgetViewport* ViewportHandle; // the objects exchanged between JS and C++ #ifdef __cplusplus extern "C" { @@ -57,7 +57,7 @@ isScheduled_ = false; } - void OnViewportChanged(const IViewport::ViewportChangedMessage& message) + void OnViewportChanged(const Deprecated::IViewport::ViewportChangedMessage& message) { if (!isScheduled_) { @@ -68,7 +68,7 @@ }; // default status bar to log messages on the console/stdout - class StatusBar : public OrthancStone::IStatusBar + class StatusBar : public Deprecated::IStatusBar { public: virtual void ClearMessage()
--- a/Platforms/Wasm/WasmDelayedCallExecutor.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmDelayedCallExecutor.cpp Tue May 21 13:25:58 2019 +0200 @@ -21,8 +21,8 @@ } else { - reinterpret_cast<OrthancStone::MessageHandler<OrthancStone::IDelayedCallExecutor::TimeoutMessage>*>(callable)-> - Apply(OrthancStone::IDelayedCallExecutor::TimeoutMessage()); // uri, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); + reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IDelayedCallExecutor::TimeoutMessage>*>(callable)-> + Apply(Deprecated::IDelayedCallExecutor::TimeoutMessage()); // uri, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); } } @@ -33,12 +33,12 @@ -namespace OrthancStone +namespace Deprecated { - MessageBroker* WasmDelayedCallExecutor::broker_ = NULL; + OrthancStone::MessageBroker* WasmDelayedCallExecutor::broker_ = NULL; - void WasmDelayedCallExecutor::Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, + void WasmDelayedCallExecutor::Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, unsigned int timeoutInMs) { WasmDelayedCallExecutor_Schedule(callback, timeoutInMs);
--- a/Platforms/Wasm/WasmDelayedCallExecutor.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmDelayedCallExecutor.h Tue May 21 13:25:58 2019 +0200 @@ -3,15 +3,15 @@ #include <Framework/Toolbox/IDelayedCallExecutor.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { class WasmDelayedCallExecutor : public IDelayedCallExecutor { private: - static MessageBroker* broker_; + static OrthancStone::MessageBroker* broker_; // Private constructor => Singleton design pattern - WasmDelayedCallExecutor(MessageBroker& broker) : + WasmDelayedCallExecutor(OrthancStone::MessageBroker& broker) : IDelayedCallExecutor(broker) { } @@ -28,12 +28,12 @@ return instance; } - static void SetBroker(MessageBroker& broker) + static void SetBroker(OrthancStone::MessageBroker& broker) { broker_ = &broker; } - virtual void Schedule(MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, + virtual void Schedule(OrthancStone::MessageHandler<IDelayedCallExecutor::TimeoutMessage>* callback, unsigned int timeoutInMs = 1000); };
--- a/Platforms/Wasm/WasmViewport.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmViewport.cpp Tue May 21 13:25:58 2019 +0200 @@ -3,11 +3,11 @@ #include <vector> #include <memory> -std::vector<std::shared_ptr<OrthancStone::WidgetViewport>> wasmViewports; +std::vector<std::shared_ptr<Deprecated::WidgetViewport>> wasmViewports; -void AttachWidgetToWasmViewport(const char* htmlCanvasId, OrthancStone::IWidget* centralWidget) { - std::shared_ptr<OrthancStone::WidgetViewport> viewport(CreateWasmViewportFromCpp(htmlCanvasId)); +void AttachWidgetToWasmViewport(const char* htmlCanvasId, Deprecated::IWidget* centralWidget) { + std::shared_ptr<Deprecated::WidgetViewport> viewport(CreateWasmViewportFromCpp(htmlCanvasId)); viewport->SetCentralWidget(centralWidget); wasmViewports.push_back(viewport); -} \ No newline at end of file +}
--- a/Platforms/Wasm/WasmViewport.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmViewport.h Tue May 21 13:25:58 2019 +0200 @@ -9,10 +9,10 @@ #endif // JS methods accessible from C++ - extern OrthancStone::WidgetViewport* CreateWasmViewportFromCpp(const char* htmlCanvasId); + extern Deprecated::WidgetViewport* CreateWasmViewportFromCpp(const char* htmlCanvasId); #ifdef __cplusplus } #endif -extern void AttachWidgetToWasmViewport(const char* htmlCanvasId, OrthancStone::IWidget* centralWidget); +extern void AttachWidgetToWasmViewport(const char* htmlCanvasId, Deprecated::IWidget* centralWidget);
--- a/Platforms/Wasm/WasmWebService.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmWebService.cpp Tue May 21 13:25:58 2019 +0200 @@ -6,9 +6,9 @@ struct CachedSuccessNotification { - boost::shared_ptr<OrthancStone::BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage; + boost::shared_ptr<Deprecated::BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage; std::auto_ptr<Orthanc::IDynamicObject> payload; - OrthancStone::MessageHandler<OrthancStone::IWebService::HttpRequestSuccessMessage>* successCallback; + OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>* successCallback; }; @@ -47,8 +47,8 @@ { if (failureCallable != NULL) { - reinterpret_cast<OrthancStone::MessageHandler<OrthancStone::IWebService::HttpRequestErrorMessage>*>(failureCallable)-> - Apply(OrthancStone::IWebService::HttpRequestErrorMessage(uri, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); + reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestErrorMessage>*>(failureCallable)-> + Apply(Deprecated::IWebService::HttpRequestErrorMessage(uri, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); } } @@ -57,7 +57,7 @@ // notification has been allocated in C++ and passed to JS. It must be deleted by this method std::auto_ptr<CachedSuccessNotification> notification(reinterpret_cast<CachedSuccessNotification*>(notification_)); - notification->successCallback->Apply(OrthancStone::IWebService::HttpRequestSuccessMessage( + notification->successCallback->Apply(Deprecated::IWebService::HttpRequestSuccessMessage( notification->cachedMessage->GetUri(), notification->cachedMessage->GetAnswer(), notification->cachedMessage->GetAnswerSize(), @@ -75,13 +75,13 @@ { if (successCallable != NULL) { - OrthancStone::IWebService::HttpHeaders headers; + Deprecated::IWebService::HttpHeaders headers; // TODO - Parse "answerHeaders" //printf("TODO: parse headers [%s]\n", answerHeaders); - reinterpret_cast<OrthancStone::MessageHandler<OrthancStone::IWebService::HttpRequestSuccessMessage>*>(successCallable)-> - Apply(OrthancStone::IWebService::HttpRequestSuccessMessage(uri, body, bodySize, headers, + reinterpret_cast<OrthancStone::MessageHandler<Deprecated::IWebService::HttpRequestSuccessMessage>*>(successCallable)-> + Apply(Deprecated::IWebService::HttpRequestSuccessMessage(uri, body, bodySize, headers, reinterpret_cast<Orthanc::IDynamicObject*>(payload))); } } @@ -92,9 +92,9 @@ -namespace OrthancStone +namespace Deprecated { - MessageBroker* WasmWebService::broker_ = NULL; + OrthancStone::MessageBroker* WasmWebService::broker_ = NULL; void ToJsonString(std::string& output, const IWebService::HttpHeaders& headers) { @@ -116,8 +116,8 @@ const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, unsigned int timeoutInSeconds) { std::string headersInJsonString; @@ -129,8 +129,8 @@ void WasmWebService::DeleteAsync(const std::string& relativeUri, const HttpHeaders& headers, Orthanc::IDynamicObject* payload, - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage>* failureCallable, unsigned int timeoutInSeconds) { std::string headersInJsonString; @@ -142,8 +142,8 @@ void WasmWebService::GetAsyncInternal(const std::string &relativeUri, const HttpHeaders &headers, Orthanc::IDynamicObject *payload, - MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable, unsigned int timeoutInSeconds) { std::string headersInJsonString; @@ -153,8 +153,8 @@ } void WasmWebService::NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedMessage, - Orthanc::IDynamicObject* payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) + Orthanc::IDynamicObject* payload, // takes ownership + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage>* successCallback) { CachedSuccessNotification* notification = new CachedSuccessNotification(); // allocated on the heap, it will be passed to JS and deleted when coming back to C++ notification->cachedMessage = cachedMessage;
--- a/Platforms/Wasm/WasmWebService.h Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/WasmWebService.h Tue May 21 13:25:58 2019 +0200 @@ -3,15 +3,15 @@ #include <Framework/Toolbox/BaseWebService.h> #include <Core/OrthancException.h> -namespace OrthancStone +namespace Deprecated { class WasmWebService : public BaseWebService { private: - static MessageBroker *broker_; + static OrthancStone::MessageBroker *broker_; // Private constructor => Singleton design pattern - WasmWebService(MessageBroker &broker) : BaseWebService(broker) + WasmWebService(OrthancStone::MessageBroker &broker) : BaseWebService(broker) { } @@ -27,7 +27,7 @@ return instance; } - static void SetBroker(MessageBroker &broker) + static void SetBroker(OrthancStone::MessageBroker &broker) { broker_ = &broker; } @@ -36,27 +36,27 @@ const HttpHeaders &headers, const std::string &body, Orthanc::IDynamicObject *payload, - MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, unsigned int timeoutInSeconds = 60); virtual void DeleteAsync(const std::string &uri, const HttpHeaders &headers, Orthanc::IDynamicObject *payload, - MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, unsigned int timeoutInSeconds = 60); protected: virtual void GetAsyncInternal(const std::string &uri, const HttpHeaders &headers, Orthanc::IDynamicObject *payload, - MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, - MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallable, + OrthancStone::MessageHandler<IWebService::HttpRequestErrorMessage> *failureCallable = NULL, unsigned int timeoutInSeconds = 60); virtual void NotifyHttpSuccessLater(boost::shared_ptr<BaseWebService::CachedHttpRequestSuccessMessage> cachedHttpMessage, Orthanc::IDynamicObject *payload, // takes ownership - MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallback); + OrthancStone::MessageHandler<IWebService::HttpRequestSuccessMessage> *successCallback); }; -} // namespace OrthancStone +} // namespace Deprecated
--- a/Platforms/Wasm/wasm-application-runner.ts Thu May 16 19:10:38 2019 +0200 +++ b/Platforms/Wasm/wasm-application-runner.ts Tue May 21 13:25:58 2019 +0200 @@ -22,6 +22,15 @@ var StartWasmApplication: Function = null; export var SendSerializedMessageToStoneApplication: Function = null; +var auxiliaryParameters : Map<string,string> = null; + +export function SetApplicationParameters(params : Map<string,string>) { + if (auxiliaryParameters != null) { + console.warn("wasm-application-runner.SetApplicationParameters: about to overwrite the existing application parameters!") + } + auxiliaryParameters = params; +} + function DoAnimationThread() { if (WasmDoAnimation != null) { WasmDoAnimation(); @@ -31,6 +40,7 @@ setTimeout(DoAnimationThread, 100); } + function GetUriParameters(): Map<string, string> { var parameters = window.location.search.substr(1); @@ -63,7 +73,16 @@ CreateWasmApplication(); - // parse uri and transmit the parameters to the app before initializing it + // transmit the API-specified parameters to the app before initializing it + for (let key in auxiliaryParameters) { + if (auxiliaryParameters.hasOwnProperty(key)) { + Logger.defaultLogger.debug( + `About to call SetStartupParameter("${key}","${auxiliaryParameters[key]}")`); + SetStartupParameter(key, auxiliaryParameters[key]); + } + } + + // parse uri and transmit the URI parameters to the app before initializing it let parameters = GetUriParameters(); for (let key in parameters) {
--- a/README.md Thu May 16 19:10:38 2019 +0200 +++ b/README.md Tue May 21 13:25:58 2019 +0200 @@ -241,17 +241,26 @@ How to build the newest (2019-04-29) SDL samples under Windows, *inside* a folder that is sibling to the orthanc-stone folder: +**Visual Studio 2017 (v140) ** + ``` cmake -G "Visual Studio 15 2017 Win64" -DMSVC_MULTIPLE_PROCESSES=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Samples/Sdl ``` +**Visual Studio 2008 (v90) ** + +``` +cmake -G "Visual Studio 9 2008" -DUSE_LEGACY_JSONCPP=ON -DENABLE_OPENGL=ON -DSTATIC_BUILD=ON -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="$($pwd)\..\orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Samples/Sdl +``` + And under Ubuntu (note the /mnt/c/osi/dev/orthanc folder): ``` cmake -G "Ninja" -DENABLE_OPENGL=ON -DSTATIC_BUILD=OFF -DOPENSSL_NO_CAPIENG=ON -DORTHANC_FRAMEWORK_SOURCE=path -DORTHANC_FRAMEWORK_ROOT="/mnt/c/osi/dev/orthanc" -DALLOW_DOWNLOADS=ON -DENABLE_SDL=ON ../orthanc-stone/Samples/Sdl ``` TODO trackers: -- text overlay 50% --> ColorTextureLayer 50% -- angle tracker: draw arcs +- CANCELLED (using outlined text now) text overlay 50% --> ColorTextureLayer 50% +- DONE angle tracker: draw arcs +- Handles on arc +- Select measure tool with hit test --> Delete command -
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Thu May 16 19:10:38 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Tue May 21 13:25:58 2019 +0200 @@ -329,6 +329,40 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2D/TextureBaseSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ZoomSceneTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/AngleMeasureTool.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/AngleMeasureTool.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateAngleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateCircleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateLineMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditAngleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditCircleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditCircleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditLineMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditLineMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/IFlexiblePointerTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureCommands.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureCommands.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTools.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTools.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureToolsToolbox.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureToolsToolbox.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTrackers.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTrackers.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/OneGesturePointerTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/OneGesturePointerTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/PointerTypes.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.h + ${ORTHANC_STONE_ROOT}/Framework/Fonts/FontRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/Glyph.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/GlyphAlphabet.cpp @@ -346,6 +380,8 @@ ${ORTHANC_STONE_ROOT}/Framework/Layers/LineMeasureTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Layers/RenderStyle.cpp ${ORTHANC_STONE_ROOT}/Framework/Layers/SliceOutlineRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Loaders/BasicFetchingItemsSorter.cpp + ${ORTHANC_STONE_ROOT}/Framework/Loaders/BasicFetchingStrategy.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyAlphaLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyDicomLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayer.cpp @@ -391,6 +427,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Toolbox/SlicesSorter.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/UndoRedoStack.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ViewportGeometry.cpp + ${ORTHANC_STONE_ROOT}/Framework/Toolbox/VolumeImageGeometry.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoContext.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoSurface.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/IMouseTracker.h
--- a/Samples/Common/AngleMeasureTool.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/** - * 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 "AngleMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include <Core/Logging.h> - -#include <boost/math/constants/constants.hpp> - -extern void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); - -namespace OrthancStone -{ - AngleMeasureTool::~AngleMeasureTool() - { - // this measuring tool is a RABI for the corresponding visual layers - // stored in the 2D scene - Disable(); - RemoveFromScene(); - } - - void AngleMeasureTool::RemoveFromScene() - { - if (layersCreated) - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - GetScene().DeleteLayer(polylineZIndex_); - GetScene().DeleteLayer(textZIndex_); - } - } - - void AngleMeasureTool::SetSide1End(ScenePoint2D pt) - { - side1End_ = pt; - RefreshScene(); - } - - void AngleMeasureTool::SetSide2End(ScenePoint2D pt) - { - side2End_ = pt; - RefreshScene(); - } - - void AngleMeasureTool::SetCenter(ScenePoint2D pt) - { - center_ = pt; - RefreshScene(); - } - - PolylineSceneLayer* AngleMeasureTool::GetPolylineLayer() - { - assert(GetScene().HasLayer(polylineZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(polylineZIndex_)); - PolylineSceneLayer* concreteLayer = dynamic_cast<PolylineSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* AngleMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - - void AngleMeasureTool::RefreshScene() - { - if (IsEnabled()) - { - // get the scaling factor - const double pixelToScene = - GetScene().GetCanvasToSceneTransform().ComputeZoom(); - - if (!layersCreated) - { - // Create the layers if need be - - assert(textZIndex_ == -1); - { - polylineZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); - GetScene().SetLayer(textZIndex_, layer.release()); - } - layersCreated = true; - } - else - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - } - { - // Fill the polyline layer with the measurement line - - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 223, 21); - - // sides - { - { - PolylineSceneLayer::Chain chain; - chain.push_back(side1End_); - chain.push_back(center_); - polylineLayer->AddChain(chain, false); - } - { - PolylineSceneLayer::Chain chain; - chain.push_back(side2End_); - chain.push_back(center_); - polylineLayer->AddChain(chain, false); - } - } - - // handles - { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), side1End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), side2End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - } - - // arc - { - PolylineSceneLayer::Chain chain; - - const double ARC_RADIUS_CANVAS_COORD = 30.0; - AddShortestArc(chain, GetScene(), side1End_, center_, side2End_, - ARC_RADIUS_CANVAS_COORD*pixelToScene); - polylineLayer->AddChain(chain, false); - } - } - { - // Set the text layer - - double p1cAngle = atan2( - side1End_.GetY() - center_.GetY(), - side1End_.GetX() - center_.GetX()); - - TrackerSample_SetInfoDisplayMessage("center_.GetX()", - boost::lexical_cast<std::string>(center_.GetX())); - - TrackerSample_SetInfoDisplayMessage("center_.GetY()", - boost::lexical_cast<std::string>(center_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", - boost::lexical_cast<std::string>(side1End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", - boost::lexical_cast<std::string>(side1End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", - boost::lexical_cast<std::string>(side2End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", - boost::lexical_cast<std::string>(side2End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", - boost::lexical_cast<std::string>(RadiansToDegrees(p1cAngle))); - - double p2cAngle = atan2( - side2End_.GetY() - center_.GetY(), - side2End_.GetX() - center_.GetX()); - - double delta = NormalizeAngle(p2cAngle - p1cAngle); - TrackerSample_SetInfoDisplayMessage("delta (deg)", - boost::lexical_cast<std::string>(RadiansToDegrees(delta))); - - double theta = p1cAngle + delta/2; - - TrackerSample_SetInfoDisplayMessage("theta (deg)", - boost::lexical_cast<std::string>(RadiansToDegrees(theta))); - - TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", - boost::lexical_cast<std::string>(RadiansToDegrees(p2cAngle))); - - const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; - - double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); - TrackerSample_SetInfoDisplayMessage("offsetX (pix)", - boost::lexical_cast<std::string>(offsetX)); - - double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); - TrackerSample_SetInfoDisplayMessage("offsetY (pix)", - boost::lexical_cast<std::string>(offsetY)); - - double pointX = center_.GetX() + offsetX * pixelToScene; - double pointY = center_.GetY() + offsetY * pixelToScene; - TrackerSample_SetInfoDisplayMessage("pointX", - boost::lexical_cast<std::string>(pointX)); - - TrackerSample_SetInfoDisplayMessage("pointY", - boost::lexical_cast<std::string>(pointY)); - - TextSceneLayer* textLayer = GetTextLayer(); - - char buf[64]; - double angleDeg = RadiansToDegrees(delta); - - TrackerSample_SetInfoDisplayMessage("angleDeg", - boost::lexical_cast<std::string>(angleDeg)); - - sprintf(buf, "%0.02f deg", angleDeg); - textLayer->SetText(buf); - textLayer->SetColor(0, 223, 21); - - ScenePoint2D textAnchor; - //GetPositionOnBisectingLine( - // textAnchor, side1End_, center_, side2End_, 40.0*pixelToScene); - textLayer->SetPosition(pointX, pointY); - } - } - else - { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } - } - } - - -}
--- a/Samples/Common/AngleMeasureTool.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -namespace OrthancStone -{ - class AngleMeasureTool : public MeasureTool - { - public: - AngleMeasureTool(MessageBroker& broker, Scene2D& scene) - : MeasureTool(broker, scene) - , layersCreated(false) - , polylineZIndex_(-1) - , textZIndex_(-1) - { - - } - - ~AngleMeasureTool(); - - void SetSide1End(ScenePoint2D start); - void SetCenter(ScenePoint2D start); - void SetSide2End(ScenePoint2D start); - - private: - PolylineSceneLayer* GetPolylineLayer(); - TextSceneLayer* GetTextLayer(); - virtual void RefreshScene() ORTHANC_OVERRIDE; - void RemoveFromScene(); - - private: - ScenePoint2D side1End_; - ScenePoint2D side2End_; - ScenePoint2D center_; - bool layersCreated; - int polylineZIndex_; - int textZIndex_; - }; - - typedef boost::shared_ptr<AngleMeasureTool> AngleMeasureToolPtr; -} - -
--- a/Samples/Common/CreateAngleMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/** - * 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 "CreateAngleMeasureTracker.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateAngleMeasureTracker::CreateAngleMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools, - const PointerEvent& e) - : CreateMeasureTracker(scene, undoStack, measureTools) - , state_(CreatingSide1) - { - command_.reset( - new CreateAngleMeasureCommand( - broker, - scene, - measureTools, - e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()))); - } - - CreateAngleMeasureTracker::~CreateAngleMeasureTracker() - { - } - - void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) - { - if (!active_) - { - throw OrthancException(ErrorCode_InternalError, - "Internal error: wrong state in CreateAngleMeasureTracker::" - "PointerMove: active_ == false"); - } - - ScenePoint2D scenePos = event.GetMainPosition().Apply( - scene_.GetCanvasToSceneTransform()); - - switch (state_) - { - case CreatingSide1: - GetCommand()->SetCenter(scenePos); - break; - case CreatingSide2: - GetCommand()->SetSide2End(scenePos); - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << - // "scenePos.GetY() = " << scenePos.GetY(); - } - - void CreateAngleMeasureTracker::PointerUp(const PointerEvent& e) - { - // TODO: the current app does not prevent multiple PointerDown AND - // PointerUp to be sent to the tracker. - // Unless we augment the PointerEvent structure with the button index, - // we cannot really tell if this pointer up event matches the initial - // pointer down event. Let's make it simple for now. - - switch (state_) - { - case CreatingSide1: - state_ = CreatingSide2; - break; - case CreatingSide2: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerUp: state_ == CreatingSide2 ; this should not happen"); - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - } - - void CreateAngleMeasureTracker::PointerDown(const PointerEvent& e) - { - switch (state_) - { - case CreatingSide1: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerDown: state_ == CreatingSide1 ; this should not happen"); - break; - case CreatingSide2: - // we are done - active_ = false; - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - } - - CreateAngleMeasureCommandPtr CreateAngleMeasureTracker::GetCommand() - { - return boost::dynamic_pointer_cast<CreateAngleMeasureCommand>(command_); - } - -}
--- a/Samples/Common/CreateAngleMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * 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 "MeasureTrackers.h" -#include "MeasureCommands.h" - -#include <vector> - -namespace OrthancStone -{ - class CreateAngleMeasureTracker : public CreateMeasureTracker - { - public: - /** - When you create this tracker, you need to supply it with the undo stack - where it will store the commands that perform the actual measure tool - creation and modification. - In turn, a container for these commands to store the actual measuring - must be supplied, too - */ - CreateAngleMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools, - const PointerEvent& e); - - ~CreateAngleMeasureTracker(); - - virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; - - private: - CreateAngleMeasureCommandPtr GetCommand(); - - enum State - { - CreatingSide1, - CreatingSide2, - Finished // just for debug - }; - State state_; - - }; -}
--- a/Samples/Common/CreateCircleMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/CreateCircleMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -}
--- a/Samples/Common/CreateLineMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/** - * 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 "CreateLineMeasureTracker.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateLineMeasureTracker::CreateLineMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools, - const PointerEvent& e) - : CreateMeasureTracker(scene, undoStack, measureTools) - { - command_.reset( - new CreateLineMeasureCommand( - broker, - scene, - measureTools, - e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()))); - } - - CreateLineMeasureTracker::~CreateLineMeasureTracker() - { - - } - - void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) - { - if (!active_) - { - throw OrthancException(ErrorCode_InternalError, - "Internal error: wrong state in CreateLineMeasureTracker::" - "PointerMove: active_ == false"); - } - - ScenePoint2D scenePos = event.GetMainPosition().Apply( - scene_.GetCanvasToSceneTransform()); - - //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << - // "scenePos.GetY() = " << scenePos.GetY(); - - CreateLineMeasureTracker* concreteThis = - dynamic_cast<CreateLineMeasureTracker*>(this); - assert(concreteThis != NULL); - GetCommand()->SetEnd(scenePos); - } - - void CreateLineMeasureTracker::PointerUp(const PointerEvent& e) - { - // TODO: the current app does not prevent multiple PointerDown AND - // PointerUp to be sent to the tracker. - // Unless we augment the PointerEvent structure with the button index, - // we cannot really tell if this pointer up event matches the initial - // pointer down event. Let's make it simple for now. - active_ = false; - } - - void CreateLineMeasureTracker::PointerDown(const PointerEvent& e) - { - LOG(WARNING) << "Additional touches (fingers, pen, mouse buttons...) " - "are ignored when the line measure creation tracker is active"; - } - - CreateLineMeasureCommandPtr CreateLineMeasureTracker::GetCommand() - { - return boost::dynamic_pointer_cast<CreateLineMeasureCommand>(command_); - } - -}
--- a/Samples/Common/CreateLineMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * 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 "MeasureTrackers.h" - -namespace OrthancStone -{ - class CreateLineMeasureTracker : public CreateMeasureTracker - { - public: - /** - When you create this tracker, you need to supply it with the undo stack - where it will store the commands that perform the actual measure tool - creation and modification. - In turn, a container for these commands to store the actual measuring - must be supplied, too - */ - CreateLineMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools, - const PointerEvent& e); - - ~CreateLineMeasureTracker(); - - virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; - - private: - CreateLineMeasureCommandPtr GetCommand(); - }; -}
--- a/Samples/Common/CreateMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -/** - * 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/>. - **/ -
--- a/Samples/Common/CreateMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * 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 -
--- a/Samples/Common/CreateSimpleTrackerAdapter.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/** - * 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 "IFlexiblePointerTracker.h" -#include <Framework/Scene2D/IPointerTracker.h> - - -namespace OrthancStone -{ - namespace - { - class SimpleTrackerAdapter : public IFlexiblePointerTracker - { - public: - SimpleTrackerAdapter(PointerTrackerPtr wrappedTracker) - : wrappedTracker_(wrappedTracker) - , active_(true) - { - } - - virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE - { - if(active_) - wrappedTracker_->Update(event); - }; - virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE - { - if (wrappedTracker_) - { - wrappedTracker_->Release(); - wrappedTracker_ = NULL; - } - active_ = false; - } - virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE - { - // nothing to do atm - } - virtual bool IsActive() const ORTHANC_OVERRIDE - { - return active_; - } - - virtual void Cancel() ORTHANC_OVERRIDE - { - wrappedTracker_ = NULL; - active_ = false; - } - - private: - PointerTrackerPtr wrappedTracker_; - bool active_; - }; - } - - FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr t) - { - return FlexiblePointerTrackerPtr(new SimpleTrackerAdapter(t)); - } -}
--- a/Samples/Common/EditAngleMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditAngleMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditCircleMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditCircleMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditLineMeasureTracker.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditLineMeasureTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -}
--- a/Samples/Common/IFlexiblePointerTracker.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/** - * 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 <Framework/Scene2D/PointerEvent.h> -#include <boost/shared_ptr.hpp> - -namespace OrthancStone -{ - class IPointerTracker; - typedef boost::shared_ptr<IPointerTracker> PointerTrackerPtr; - - /** - This interface represents a flexible mouse tracker that can respond to - several events and is not automatically deleted upon mouse up or when touch - interaction is suspended : for instance, a stateful tracker with a two-step - interaction like: click & drag --> mouse up --> drag --> mouse click - (for instance, for an angle measuring tracker or an ellipse tracker) - */ - class IFlexiblePointerTracker : public boost::noncopyable - { - public: - virtual ~IFlexiblePointerTracker() {} - - /** - This method will be repeatedly called during user interaction - */ - virtual void PointerMove(const PointerEvent& event) = 0; - - /** - This method will be called when a touch/pointer is removed (mouse up, - pen lift, finger removed...) - */ - virtual void PointerUp(const PointerEvent& event) = 0; - - /** - This method will be called when a touch/pointer is added (mouse down, - pen or finger press) - */ - virtual void PointerDown(const PointerEvent& event) = 0; - - /** - This method will be repeatedly called by the tracker owner (for instance, - the application) to check whether the tracker must keep on receiving - interaction or if its job is done and it should be deleted. - */ - virtual bool IsActive() const = 0; - - /** - This will be called if the tracker needs to be dismissed without committing - its changes to the underlying model. If the model has been modified during - tracker lifetime, it must be restored to its initial value - */ - virtual void Cancel() = 0; - }; - - typedef boost::shared_ptr<IFlexiblePointerTracker> FlexiblePointerTrackerPtr; - - /** - This factory adopts the supplied simple tracker and creates a flexible - tracker wrapper around it. - */ - FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); -} -
--- a/Samples/Common/LineMeasureTool.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -/** - * 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 "LineMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include <Core/Logging.h> - - -namespace OrthancStone -{ - LineMeasureTool::~LineMeasureTool() - { - // this measuring tool is a RABI for the corresponding visual layers - // stored in the 2D scene - Disable(); - RemoveFromScene(); - } - - void LineMeasureTool::RemoveFromScene() - { - if (layersCreated) - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - GetScene().DeleteLayer(polylineZIndex_); - GetScene().DeleteLayer(textZIndex_); - } - } - - - void LineMeasureTool::SetStart(ScenePoint2D start) - { - start_ = start; - RefreshScene(); - } - - void LineMeasureTool::SetEnd(ScenePoint2D end) - { - end_ = end; - RefreshScene(); - } - - void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end) - { - start_ = start; - end_ = end; - RefreshScene(); - } - - PolylineSceneLayer* LineMeasureTool::GetPolylineLayer() - { - assert(GetScene().HasLayer(polylineZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(polylineZIndex_)); - PolylineSceneLayer* concreteLayer = dynamic_cast<PolylineSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* LineMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - void LineMeasureTool::RefreshScene() - { - if (IsEnabled()) - { - if (!layersCreated) - { - // Create the layers if need be - - assert(textZIndex_ == -1); - { - polylineZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); - GetScene().SetLayer(textZIndex_, layer.release()); - } - layersCreated = true; - } - else - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - } - { - // Fill the polyline layer with the measurement line - - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 223, 21); - - { - PolylineSceneLayer::Chain chain; - chain.push_back(start_); - chain.push_back(end_); - polylineLayer->AddChain(chain, false); - } - - // handles - { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), start_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), end_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - //ScenePoint2D startC = start_.Apply(GetScene().GetSceneToCanvasTransform()); - //double squareSize = 10.0; - //double startHandleLX = startC.GetX() - squareSize/2; - //double startHandleTY = startC.GetY() - squareSize / 2; - //double startHandleRX = startC.GetX() + squareSize / 2; - //double startHandleBY = startC.GetY() + squareSize / 2; - //ScenePoint2D startLTC(startHandleLX, startHandleTY); - //ScenePoint2D startRTC(startHandleRX, startHandleTY); - //ScenePoint2D startRBC(startHandleRX, startHandleBY); - //ScenePoint2D startLBC(startHandleLX, startHandleBY); - - //ScenePoint2D startLT = startLTC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startRT = startRTC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startRB = startRBC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startLB = startLBC.Apply(GetScene().GetCanvasToSceneTransform()); - - //PolylineSceneLayer::Chain chain; - //chain.push_back(startLT); - //chain.push_back(startRT); - //chain.push_back(startRB); - //chain.push_back(startLB); - //polylineLayer->AddChain(chain, true); - } - - } - { - // Set the text layer proporeties - - TextSceneLayer* textLayer = GetTextLayer(); - double deltaX = end_.GetX() - start_.GetX(); - double deltaY = end_.GetY() - start_.GetY(); - double squareDist = deltaX * deltaX + deltaY * deltaY; - double dist = sqrt(squareDist); - char buf[64]; - sprintf(buf, "%0.02f units", dist); - textLayer->SetText(buf); - textLayer->SetColor(0, 223, 21); - - // TODO: for now we simply position the text overlay at the middle - // of the measuring segment - double midX = 0.5*(end_.GetX() + start_.GetX()); - double midY = 0.5*(end_.GetY() + start_.GetY()); - textLayer->SetPosition(midX, midY); - } - } - else - { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } - } - } - - -} \ No newline at end of file
--- a/Samples/Common/LineMeasureTool.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -namespace OrthancStone -{ - class LineMeasureTool : public MeasureTool - { - public: - LineMeasureTool(MessageBroker& broker, Scene2D& scene) - : MeasureTool(broker, scene) - , layersCreated(false) - , polylineZIndex_(-1) - , textZIndex_(-1) - { - - } - - ~LineMeasureTool(); - - void SetStart(ScenePoint2D start); - void SetEnd(ScenePoint2D end); - void Set(ScenePoint2D start, ScenePoint2D end); - - private: - PolylineSceneLayer* GetPolylineLayer(); - TextSceneLayer* GetTextLayer(); - virtual void RefreshScene() ORTHANC_OVERRIDE; - void RemoveFromScene(); - - private: - ScenePoint2D start_; - ScenePoint2D end_; - bool layersCreated; - int polylineZIndex_; - int textZIndex_; - }; - - typedef boost::shared_ptr<LineMeasureTool> LineMeasureToolPtr; -} -
--- a/Samples/Common/MeasureCommands.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * 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 "MeasureCommands.h" - -namespace OrthancStone -{ - void CreateMeasureCommand::Undo() - { - // simply disable the measure tool upon undo - GetMeasureTool()->Disable(); - } - - void CreateMeasureCommand::Redo() - { - GetMeasureTool()->Enable(); - } - - CreateMeasureCommand::CreateMeasureCommand( - Scene2D& scene, MeasureToolList& measureTools) - : TrackerCommand(scene) - , measureTools_(measureTools) - { - - } - - CreateMeasureCommand::~CreateMeasureCommand() - { - // deleting the command should not change the model state - // we thus leave it as is - } - - CreateLineMeasureCommand::CreateLineMeasureCommand( - MessageBroker& broker, - Scene2D& scene, - MeasureToolList& measureTools, - ScenePoint2D point) - : CreateMeasureCommand(scene, measureTools) - , measureTool_(new LineMeasureTool(broker,scene)) - { - measureTools_.push_back(measureTool_); - measureTool_->Set(point, point); - } - - void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos) - { - measureTool_->SetEnd(scenePos); - } - - CreateAngleMeasureCommand::CreateAngleMeasureCommand( - MessageBroker& broker, - Scene2D& scene, - MeasureToolList& measureTools, - ScenePoint2D point) - : CreateMeasureCommand(scene, measureTools) - , measureTool_(new AngleMeasureTool(broker,scene)) - { - measureTools_.push_back(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/Samples/Common/MeasureCommands.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/** - * 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 <Framework/Scene2D/Scene2D.h> -#include <boost/shared_ptr.hpp> - -// to be moved into Stone -#include "MeasureTools.h" -#include "LineMeasureTool.h" -#include "AngleMeasureTool.h" - -namespace OrthancStone -{ - //class LineMeasureTool; - //typedef boost::shared_ptr<LineMeasureTool> LineMeasureToolPtr; - //class AngleMeasureTool; - //typedef boost::shared_ptr<AngleMeasureTool> AngleMeasureToolPtr; - - class TrackerCommand - { - public: - TrackerCommand(Scene2D& scene) : scene_(scene) - { - - } - virtual void Undo() = 0; - virtual void Redo() = 0; - Scene2D& GetScene() - { - return scene_; - } - - protected: - Scene2D& scene_; - private: - TrackerCommand(const TrackerCommand&); - TrackerCommand& operator=(const TrackerCommand&); - }; - - typedef boost::shared_ptr<TrackerCommand> TrackerCommandPtr; - - class CreateMeasureCommand : public TrackerCommand - { - public: - CreateMeasureCommand(Scene2D& scene, MeasureToolList& measureTools); - ~CreateMeasureCommand(); - virtual void Undo() ORTHANC_OVERRIDE; - virtual void Redo() ORTHANC_OVERRIDE; - protected: - MeasureToolList& measureTools_; - private: - /** Must be implemented by the subclasses that create the actual tool */ - virtual MeasureToolPtr GetMeasureTool() = 0; - }; - - typedef boost::shared_ptr<CreateMeasureCommand> CreateMeasureCommandPtr; - - class CreateLineMeasureCommand : public CreateMeasureCommand - { - public: - CreateLineMeasureCommand( - MessageBroker& broker, Scene2D& scene, MeasureToolList& measureTools, ScenePoint2D point); - - // the starting position is set in the ctor - void SetEnd(ScenePoint2D scenePos); - - private: - virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE - { - return measureTool_; - } - LineMeasureToolPtr measureTool_; - }; - - typedef boost::shared_ptr<CreateLineMeasureCommand> CreateLineMeasureCommandPtr; - - class CreateAngleMeasureCommand : public CreateMeasureCommand - { - public: - /** Ctor sets end of side 1*/ - CreateAngleMeasureCommand( - MessageBroker& broker, Scene2D& scene, MeasureToolList& measureTools, ScenePoint2D point); - - /** This method sets center*/ - void SetCenter(ScenePoint2D scenePos); - - /** This method sets end of side 2*/ - void SetSide2End(ScenePoint2D scenePos); - - private: - virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE - { - return measureTool_; - } - AngleMeasureToolPtr measureTool_; - }; - - typedef boost::shared_ptr<CreateAngleMeasureCommand> CreateAngleMeasureCommandPtr; -} -
--- a/Samples/Common/MeasureTools.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include <Core/Logging.h> - -#include <boost/math/constants/constants.hpp> - -namespace OrthancStone -{ - - MeasureTool::~MeasureTool() - { - - } - - void MeasureTool::Enable() - { - enabled_ = true; - RefreshScene(); - } - - void MeasureTool::Disable() - { - enabled_ = false; - RefreshScene(); - } - - bool MeasureTool::IsEnabled() const - { - return enabled_; - } - - OrthancStone::Scene2D& MeasureTool::GetScene() - { - return scene_; - } - - MeasureTool::MeasureTool(MessageBroker& broker, Scene2D& scene) - : IObserver(broker) - , scene_(scene) - , enabled_(true) - { - scene_.RegisterObserverCallback( - new Callable<MeasureTool, Scene2D::SceneTransformChanged> - (*this, &MeasureTool::OnSceneTransformChanged)); - } - - void MeasureTool::OnSceneTransformChanged( - const Scene2D::SceneTransformChanged& message) - { - RefreshScene(); - } - - -} -
--- a/Samples/Common/MeasureTools.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/** - * 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 <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -namespace OrthancStone -{ - class MeasureTool : public IObserver - { - public: - virtual ~MeasureTool(); - - /** - Enabled tools are rendered in the scene. - */ - void Enable(); - - /** - Disabled tools are not rendered in the scene. This is useful to be able - to use them as their own memento in command stacks (when a measure tool - creation command has been undone, the measure remains alive in the - command object but is disabled so that it can be redone later on easily) - */ - void Disable(); - - /** - This method is called when the scene transform changes. It allows to - recompute the visual elements whose content depend upon the scene transform - */ - void OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message); - - protected: - MeasureTool(MessageBroker& broker, Scene2D& scene); - - /** - This is the meat of the tool: this method must [create (if needed) and] - update the layers and their data according to the measure tool kind and - current state. This is repeatedly called during user interaction - */ - virtual void RefreshScene() = 0; - - Scene2D& GetScene(); - - /** - enabled_ is not accessible by subclasses because there is a state machine - that we do not wanna mess with - */ - bool IsEnabled() const; - - private: - Scene2D& scene_; - bool enabled_; - }; - - typedef boost::shared_ptr<MeasureTool> MeasureToolPtr; - typedef std::vector<MeasureToolPtr> MeasureToolList; -} - - -extern void TrackerSample_SetInfoDisplayMessage( - std::string key, std::string value);
--- a/Samples/Common/MeasureToolsToolbox.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -/** - * 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 "MeasureToolsToolbox.h" - -#include <boost/math/constants/constants.hpp> - -namespace -{ - double g_pi = boost::math::constants::pi<double>(); -} - -namespace OrthancStone -{ - double RadiansToDegrees(double angleRad) - { - static const double factor = 180.0 / g_pi; - return angleRad * factor; - } - - void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& sideLength) - { - chain.clear(); - chain.reserve(4); - ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - double handleLX = centerC.GetX() - sideLength / 2; - double handleTY = centerC.GetY() - sideLength / 2; - double handleRX = centerC.GetX() + sideLength / 2; - double handleBY = centerC.GetY() + sideLength / 2; - ScenePoint2D LTC(handleLX, handleTY); - ScenePoint2D RTC(handleRX, handleTY); - ScenePoint2D RBC(handleRX, handleBY); - ScenePoint2D LBC(handleLX, handleBY); - - ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); - - chain.push_back(startLT); - chain.push_back(startRT); - chain.push_back(startRB); - chain.push_back(startLB); - } -#if 0 - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const bool clockwise - , const int subdivisionsCount) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - AddArc( - chain, scene, c, radiusS, p1cAngle, p2cAngle, - clockwise, subdivisionsCount); - } -#endif - - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const int subdivisionsCount) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - AddShortestArc( - chain, scene, c, radiusS, p1cAngle, p2cAngle, subdivisionsCount); - } - - void GetPositionOnBisectingLine( - ScenePoint2D& result - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double d) - { - // TODO: fix correct half-plane - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - double angle = 0.5*(p1cAngle + p2cAngle); - double unitVectorX = cos(angle); - double unitVectorY = sin(angle); - double posX = c.GetX() + d * unitVectorX; - double posY = c.GetX() + d * unitVectorY; - result = ScenePoint2D(posX, posY); - } - - - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const int subdivisionsCount) - { - // this gives a signed difference between angle which - // is the smallest difference (in magnitude) between - // the angles - double delta = NormalizeAngle(endAngleRad-startAngleRad); - - chain.clear(); - chain.reserve(subdivisionsCount + 1); - - double angleIncr = delta/static_cast<double>(subdivisionsCount); - - double theta = startAngleRad; - for (int i = 0; i < subdivisionsCount + 1; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } - -#if 0 - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const bool clockwise - , const int subdivisionsCount) - { - double startAngleRadN = NormalizeAngle(startAngleRad); - double endAngleRadN = NormalizeAngle(endAngleRad); - - double angle1Rad = std::min(startAngleRadN, endAngleRadN); - double angle2Rad = std::max(startAngleRadN, endAngleRadN); - - // now we are sure angle1Rad < angle2Rad - // this means that if we draw from 1 to 2, it will be clockwise ( - // increasing angles). - // let's fix this: - if (!clockwise) - { - angle2Rad -= 2 * g_pi; - // now we are sure angle2Rad < angle1Rad (since they were normalized) - // and, thus, going from 1 to 2 means the angle values will DECREASE, - // which is the definition of anticlockwise - } - - chain.clear(); - chain.reserve(subdivisionsCount + 1); - - double angleIncr = (angle2Rad - angle1Rad) - / static_cast<double>(subdivisionsCount); - - double theta = angle1Rad; - for (int i = 0; i < subdivisionsCount + 1; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } -#endif - - void AddCircle(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& radiusS, - const int numSubdivisions) - { - //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - - // TODO: automatically compute the number for segments for smooth - // display based on the radius in pixels. - - chain.clear(); - chain.reserve(numSubdivisions); - - double angleIncr = (2.0 * g_pi) - / static_cast<double>(numSubdivisions); - - double theta = 0; - for (int i = 0; i < numSubdivisions; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } - - double NormalizeAngle(double angle) - { - double retAngle = angle; - while (retAngle < -1.0*g_pi) - retAngle += 2 * g_pi; - while (retAngle >= g_pi) - retAngle -= 2 * g_pi; - return retAngle; - } - - double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - double delta = p2cAngle - p1cAngle; - return NormalizeAngle(delta); - } - - -#if 0 - void AddEllipse(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& halfHAxis, - const double& halfVAxis) - { - chain.clear(); - chain.reserve(4); - ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - double handleLX = centerC.GetX() - sideLength / 2; - double handleTY = centerC.GetY() - sideLength / 2; - double handleRX = centerC.GetX() + sideLength / 2; - double handleBY = centerC.GetY() + sideLength / 2; - ScenePoint2D LTC(handleLX, handleTY); - ScenePoint2D RTC(handleRX, handleTY); - ScenePoint2D RBC(handleRX, handleBY); - ScenePoint2D LBC(handleLX, handleBY); - - ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); - - chain.push_back(startLT); - chain.push_back(startRT); - chain.push_back(startRB); - chain.push_back(startLB); -} -#endif -}
--- a/Samples/Common/MeasureToolsToolbox.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/** - * 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 <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/Scene2D.h> - -namespace OrthancStone -{ - - /** - This function will create a square around the center point supplied in - scene coordinates, with a side length given in canvas coordinates. The - square sides are parallel to the canvas boundaries. - */ - void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& sideLength); - - - /** - Creates an arc centered on c that goes - - from a point r1: - - so that r1 belongs to the p1,c line - - so that the distance from c to r1 equals radius - - to a point r2: - - so that r2 belongs to the p2,c line - - so that the distance from c to r2 equals radius - - that follows the shortest among the two possible paths - - Warning: the existing chain content will be wiped out. - */ - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const int subdivisionsCount = 63); - - /** - Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from - start angle to end angle, by following the shortest arc. - - Warning: the existing chain content will be wiped out. - */ - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const int subdivisionsCount = 63); - -#if 0 - /** - Creates an arc centered on c that goes - - from a point r1: - - so that r1 belongs to the p1,c line - - so that the distance from c to r1 equals radius - - to a point r2: - - so that r2 belongs to the p2,c line - - so that the distance from c to r2 equals radius - - if clockwise is true, the arc is drawn from r1 to r2 with increasing - angle values. Otherwise, the angle values decrease. - - Warning: the existing chain content will be wiped out. - */ - - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const bool clockwise - , const int subdivisionsCount = 63); - - /** - Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from - start angle to end angle with the supplied radius. - - if clockwise is true, the arc is drawn from start to end by increasing the - angle values. - - Otherwise, the angle value decreases from start to end. - - Warning: the existing chain content will be wiped out. - */ - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const bool clockwise - , const int subdivisionsCount = 63); -#endif - /** - Creates a circle (closed curve) with "numSubdivisions" - (N points) - - Warning: the existing chain content will be wiped out. - */ - void AddCircle(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& radiusS, - const int numSubdivisions = 63); - - /** - Adds or subtracts 2*pi as many times as need to shift the specified - angle to a value such as: -pi <= value < pi - */ - double NormalizeAngle(double angle); - - /** - Returns the angle magnitude between the p1,c and p2,c lines. - The returned angle is between 0 and 2*pi - - If the angle is between 0 and pi, this means that the shortest arc - from p1 to p2 is clockwise. - - If the angle is between pi and 2*pi, this means that the shortest arc - from p1 to p2 is COUNTERclockwise. - - */ - double MeasureAngle( - const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2); - - /** - RadiansToDegrees - */ - double RadiansToDegrees(double angleRad); - - /** - This function will return the coordinates of a point that: - - belongs to the two bisecting lines of the p1 c p2 angle. - - is a distance d from c. - Among the four possible points, the one returned will be the one belonging - to the *smallest* half-plane defined by the [c,p1[ and [c,p2[ half-lines. - */ - void GetPositionOnBisectingLine( - ScenePoint2D& result - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double d); -}
--- a/Samples/Common/MeasureTrackers.cpp Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * 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 "MeasureTrackers.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - - CreateMeasureTracker::CreateMeasureTracker( - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools) - : scene_(scene) - , active_(true) - , undoStack_(undoStack) - , measureTools_(measureTools) - , commitResult_(true) - { - } - - void CreateMeasureTracker::Cancel() - { - commitResult_ = false; - active_ = false; - } - - bool CreateMeasureTracker::IsActive() const - { - return active_; - } - - CreateMeasureTracker::~CreateMeasureTracker() - { - // if the tracker completes successfully, we add the command - // to the undo stack - - // otherwise, we simply undo it - if (commitResult_) - undoStack_.push_back(command_); - else - command_->Undo(); - } -} - -
--- a/Samples/Common/MeasureTrackers.h Thu May 16 19:10:38 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * 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 "IFlexiblePointerTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/PointerEvent.h" - -#include "MeasureTools.h" -#include "MeasureCommands.h" - -#include <vector> - -namespace OrthancStone -{ - class CreateMeasureTracker : public IFlexiblePointerTracker - { - public: - virtual void Cancel() ORTHANC_OVERRIDE; - virtual bool IsActive() const ORTHANC_OVERRIDE; - protected: - CreateMeasureTracker( - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools); - - ~CreateMeasureTracker(); - - protected: - CreateMeasureCommandPtr command_; - Scene2D& scene_; - bool active_; - private: - std::vector<TrackerCommandPtr>& undoStack_; - std::vector<MeasureToolPtr>& measureTools_; - bool commitResult_; - }; -} -
--- a/Samples/Sdl/BasicScene.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Samples/Sdl/BasicScene.cpp Tue May 21 13:25:58 2019 +0200 @@ -28,6 +28,8 @@ #include "../../Framework/Scene2D/RotateSceneTracker.h" #include "../../Framework/Scene2D/Scene2D.h" #include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2DViewport/ViewportController.h" + #include "../../Framework/StoneInitialization.h" #include "../../Framework/Messages/MessageBroker.h" @@ -38,17 +40,20 @@ #include <Core/Images/ImageProcessing.h> #include <Core/Images/PngWriter.h> +#include <boost/make_shared.hpp> +#include <boost/ref.hpp> + #include <SDL.h> #include <stdio.h> static const unsigned int FONT_SIZE = 32; static const int LAYER_POSITION = 150; +using namespace OrthancStone; -void PrepareScene(OrthancStone::Scene2D& scene) +void PrepareScene(ViewportControllerPtr controller) { - using namespace OrthancStone; - + Scene2D& scene(*controller->GetScene()); // Texture of 2x2 size { Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); @@ -137,12 +142,12 @@ void TakeScreenshot(const std::string& target, - const OrthancStone::Scene2D& scene, + const Scene2D& scene, unsigned int canvasWidth, unsigned int canvasHeight) { // Take a screenshot, then save it as PNG file - OrthancStone::CairoCompositor compositor(scene, canvasWidth, canvasHeight); + CairoCompositor compositor(scene, canvasWidth, canvasHeight); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); compositor.Refresh(); @@ -157,11 +162,12 @@ } -void HandleApplicationEvent(OrthancStone::Scene2D& scene, - const OrthancStone::OpenGLCompositor& compositor, +void HandleApplicationEvent(ViewportControllerPtr controller, + const OpenGLCompositor& compositor, const SDL_Event& event, - std::auto_ptr<OrthancStone::IPointerTracker>& activeTracker) + FlexiblePointerTrackerPtr& activeTracker) { + Scene2D& scene(*controller->GetScene()); if (event.type == SDL_MOUSEMOTION) { int scancodeCount = 0; @@ -173,28 +179,29 @@ { // The "left-ctrl" key is down, while no tracker is present - OrthancStone::PointerEvent e; + PointerEvent e; e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - OrthancStone::ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); char buf[64]; sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); if (scene.HasLayer(LAYER_POSITION)) { - OrthancStone::TextSceneLayer& layer = - dynamic_cast<OrthancStone::TextSceneLayer&>(scene.GetLayer(LAYER_POSITION)); + TextSceneLayer& layer = + dynamic_cast<TextSceneLayer&>(scene.GetLayer(LAYER_POSITION)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } else { - std::auto_ptr<OrthancStone::TextSceneLayer> layer(new OrthancStone::TextSceneLayer); + std::auto_ptr<TextSceneLayer> + layer(new TextSceneLayer); layer->SetColor(0, 255, 0); layer->SetText(buf); layer->SetBorder(20); - layer->SetAnchor(OrthancStone::BitmapAnchor_BottomCenter); + layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); scene.SetLayer(LAYER_POSITION, layer.release()); } @@ -206,22 +213,22 @@ } else if (event.type == SDL_MOUSEBUTTONDOWN) { - OrthancStone::PointerEvent e; + PointerEvent e; e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); switch (event.button.button) { case SDL_BUTTON_MIDDLE: - activeTracker.reset(new OrthancStone::PanSceneTracker(scene, e)); + activeTracker = boost::make_shared<PanSceneTracker>(controller, e); break; case SDL_BUTTON_RIGHT: - activeTracker.reset(new OrthancStone::ZoomSceneTracker(scene, e, - compositor.GetCanvasHeight())); + activeTracker = boost::make_shared<ZoomSceneTracker>(controller, + e, compositor.GetCanvasHeight()); break; case SDL_BUTTON_LEFT: - activeTracker.reset(new OrthancStone::RotateSceneTracker(scene, e)); + activeTracker = boost::make_shared<RotateSceneTracker>(controller, e); break; default: @@ -234,7 +241,7 @@ switch (event.key.keysym.sym) { case SDLK_s: - scene.FitContent(compositor.GetCanvasWidth(), + controller->FitContent(compositor.GetCanvasWidth(), compositor.GetCanvasHeight()); break; @@ -269,20 +276,20 @@ } -void Run(OrthancStone::Scene2D& scene) +void Run(ViewportControllerPtr controller) { - OrthancStone::SdlOpenGLWindow window("Hello", 1024, 768); + SdlOpenGLWindow window("Hello", 1024, 768); - scene.FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + controller->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - OrthancStone::OpenGLCompositor compositor(window, scene); + OpenGLCompositor compositor(window, *controller->GetScene()); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); - std::auto_ptr<OrthancStone::IPointerTracker> tracker; + FlexiblePointerTrackerPtr tracker; bool stop = false; while (!stop) @@ -300,25 +307,30 @@ } else if (event.type == SDL_MOUSEMOTION) { - if (tracker.get() != NULL) + if (tracker) { - OrthancStone::PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - tracker->Update(e); + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerMove(e); } } else if (event.type == SDL_MOUSEBUTTONUP) { - if (tracker.get() != NULL) + if (tracker) { - tracker->Release(); - tracker.reset(NULL); + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerUp(e); + if(!tracker->IsAlive()) + tracker.reset(); } } else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - tracker.reset(NULL); + tracker.reset(); compositor.UpdateSize(); } else if (event.type == SDL_KEYDOWN && @@ -339,7 +351,7 @@ } } - HandleApplicationEvent(scene, compositor, event, tracker); + HandleApplicationEvent(controller, compositor, event, tracker); } SDL_Delay(1); @@ -356,22 +368,23 @@ **/ int main(int argc, char* argv[]) { - OrthancStone::StoneInitialize(); + StoneInitialize(); Orthanc::Logging::EnableInfoLevel(true); try { - OrthancStone::MessageBroker broker; - OrthancStone::Scene2D scene(broker); - PrepareScene(scene); - Run(scene); + MessageBroker broker; + ViewportControllerPtr controller = boost::make_shared<ViewportController>( + boost::ref(broker)); + PrepareScene(controller); + Run(controller); } catch (Orthanc::OrthancException& e) { LOG(ERROR) << "EXCEPTION: " << e.What(); } - OrthancStone::StoneFinalize(); + StoneFinalize(); return 0; }
--- a/Samples/Sdl/CMakeLists.txt Thu May 16 19:10:38 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Tue May 21 13:25:58 2019 +0200 @@ -69,44 +69,6 @@ LIST(APPEND TRACKERSAMPLE_SOURCE "../../../SDL-Console/SDL_Console.h") endif() -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/AngleMeasureTool.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/AngleMeasureTool.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateAngleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateAngleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateCircleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateCircleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateLineMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateLineMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateSimpleTrackerAdapter.cpp") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditAngleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditAngleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditCircleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditCircleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditLineMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditLineMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/IFlexiblePointerTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/LineMeasureTool.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/LineMeasureTool.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureCommands.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureCommands.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTools.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTools.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureToolsToolbox.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureToolsToolbox.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTrackers.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTrackers.h") - LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSample.cpp") LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.cpp") LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.h")
--- a/Samples/Sdl/Loader.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Tue May 21 13:25:58 2019 +0200 @@ -19,14 +19,19 @@ **/ // From Stone +#include "../../Framework/Loaders/BasicFetchingItemsSorter.h" +#include "../../Framework/Loaders/BasicFetchingStrategy.h" #include "../../Framework/Messages/ICallable.h" #include "../../Framework/Messages/IMessage.h" #include "../../Framework/Messages/IObservable.h" #include "../../Framework/Messages/MessageBroker.h" +#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" +#include "../../Framework/Scene2D/FloatTextureSceneLayer.h" +#include "../../Framework/Scene2D/Scene2D.h" #include "../../Framework/StoneInitialization.h" #include "../../Framework/Toolbox/GeometryToolbox.h" +#include "../../Framework/Toolbox/SlicesSorter.h" #include "../../Framework/Volumes/ImageBuffer3D.h" -#include "../../Framework/Toolbox/SlicesSorter.h" // From Orthanc framework #include <Core/Compression/GzipCompressor.h> @@ -44,8 +49,8 @@ #include <Core/Logging.h> #include <Core/MultiThreading/SharedMessageQueue.h> #include <Core/OrthancException.h> +#include <Core/SystemToolbox.h> #include <Core/Toolbox.h> -#include <Core/SystemToolbox.h> #include <json/reader.h> #include <json/value.h> @@ -101,6 +106,17 @@ + class IVolumeSlicer : public boost::noncopyable + { + public: + virtual ~IVolumeSlicer() + { + } + + virtual void SetViewportPlane(const OrthancStone::CoordinateSystem3D& plane) = 0; + }; + + class OracleCommandWithPayload : public IOracleCommand { @@ -354,9 +370,11 @@ private: - std::string uri_; - HttpHeaders headers_; - unsigned int timeout_; + std::string uri_; + HttpHeaders headers_; + unsigned int timeout_; + bool hasExpectedFormat_; + Orthanc::PixelFormat expectedFormat_; std::auto_ptr< OrthancStone::MessageHandler<SuccessMessage> > successCallback_; std::auto_ptr< OrthancStone::MessageHandler<OracleCommandExceptionMessage> > failureCallback_; @@ -364,7 +382,8 @@ public: GetOrthancImageCommand() : uri_("/"), - timeout_(10) + timeout_(10), + hasExpectedFormat_(false) { } @@ -373,11 +392,41 @@ return Type_GetOrthancImage; } + void SetExpectedPixelFormat(Orthanc::PixelFormat format) + { + hasExpectedFormat_ = true; + expectedFormat_ = format; + } + void SetUri(const std::string& uri) { uri_ = uri; } + void SetInstanceUri(const std::string& instance, + Orthanc::PixelFormat pixelFormat) + { + uri_ = "/instances/" + instance; + + switch (pixelFormat) + { + case Orthanc::PixelFormat_RGB24: + uri_ += "/preview"; + break; + + case Orthanc::PixelFormat_Grayscale16: + uri_ += "/image-uint16"; + break; + + case Orthanc::PixelFormat_SignedGrayscale16: + uri_ += "/image-int16"; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + void SetHttpHeader(const std::string& key, const std::string& value) { @@ -455,6 +504,20 @@ std::string(Orthanc::EnumerationToString(contentType))); } + if (hasExpectedFormat_) + { + if (expectedFormat_ == Orthanc::PixelFormat_SignedGrayscale16 && + image->GetFormat() == Orthanc::PixelFormat_Grayscale16) + { + image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); + } + + if (expectedFormat_ != image->GetFormat()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); + } + } + SuccessMessage message(*this, image.release(), contentType); emitter.EmitMessage(receiver, message); } @@ -515,7 +578,7 @@ return Type_GetOrthancWebViewerJpeg; } - void SetExpectedFormat(Orthanc::PixelFormat format) + void SetExpectedPixelFormat(Orthanc::PixelFormat format) { expectedFormat_ = format; } @@ -549,7 +612,7 @@ headers_[key] = value; } - Orthanc::PixelFormat GetExpectedFormat() const + Orthanc::PixelFormat GetExpectedPixelFormat() const { return expectedFormat_; } @@ -734,6 +797,1127 @@ + class DicomInstanceParameters : + public Orthanc::IDynamicObject /* to be used as a payload of SlicesSorter */ + { + private: + struct Data // Struct to ease the copy constructor + { + std::string orthancInstanceId_; + std::string studyInstanceUid_; + std::string seriesInstanceUid_; + std::string sopInstanceUid_; + Orthanc::DicomImageInformation imageInformation_; + OrthancStone::SopClassUid sopClassUid_; + double thickness_; + double pixelSpacingX_; + double pixelSpacingY_; + OrthancStone::CoordinateSystem3D geometry_; + OrthancStone::Vector frameOffsets_; + bool isColor_; + bool hasRescale_; + double rescaleIntercept_; + double rescaleSlope_; + bool hasDefaultWindowing_; + float defaultWindowingCenter_; + float defaultWindowingWidth_; + Orthanc::PixelFormat expectedPixelFormat_; + + void ComputeDoseOffsets(const Orthanc::DicomMap& dicom) + { + // http://dicom.nema.org/medical/Dicom/2016a/output/chtml/part03/sect_C.8.8.3.2.html + + { + std::string increment; + + if (dicom.CopyToString(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) + { + Orthanc::Toolbox::ToUpperCase(increment); + if (increment != "3004,000C") // This is the "Grid Frame Offset Vector" tag + { + LOG(ERROR) << "RT-DOSE: Bad value for the \"FrameIncrementPointer\" tag"; + return; + } + } + } + + if (!OrthancStone::LinearAlgebra::ParseVector(frameOffsets_, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) || + frameOffsets_.size() < imageInformation_.GetNumberOfFrames()) + { + LOG(ERROR) << "RT-DOSE: No information about the 3D location of some slice(s)"; + frameOffsets_.clear(); + } + else + { + if (frameOffsets_.size() >= 2) + { + thickness_ = frameOffsets_[1] - frameOffsets_[0]; + + if (thickness_ < 0) + { + thickness_ = -thickness_; + } + } + } + } + + Data(const Orthanc::DicomMap& dicom) : + imageInformation_(dicom) + { + if (imageInformation_.GetNumberOfFrames() <= 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + if (!dicom.CopyToString(studyInstanceUid_, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false) || + !dicom.CopyToString(seriesInstanceUid_, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, false) || + !dicom.CopyToString(sopInstanceUid_, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + std::string s; + if (!dicom.CopyToString(s, Orthanc::DICOM_TAG_SOP_CLASS_UID, false)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + else + { + sopClassUid_ = OrthancStone::StringToSopClassUid(s); + } + + if (!dicom.ParseDouble(thickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS)) + { + thickness_ = 100.0 * std::numeric_limits<double>::epsilon(); + } + + OrthancStone::GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom); + + std::string position, orientation; + if (dicom.CopyToString(position, Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT, false) && + dicom.CopyToString(orientation, Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT, false)) + { + geometry_ = OrthancStone::CoordinateSystem3D(position, orientation); + } + + if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) + { + ComputeDoseOffsets(dicom); + } + + isColor_ = (imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome1 && + imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome2); + + double doseGridScaling; + + if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && + dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) + { + hasRescale_ = true; + } + else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) + { + hasRescale_ = true; + rescaleIntercept_ = 0; + rescaleSlope_ = doseGridScaling; + } + else + { + hasRescale_ = false; + } + + OrthancStone::Vector c, w; + if (OrthancStone::LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && + OrthancStone::LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && + c.size() > 0 && + w.size() > 0) + { + hasDefaultWindowing_ = true; + defaultWindowingCenter_ = static_cast<float>(c[0]); + defaultWindowingWidth_ = static_cast<float>(w[0]); + } + else + { + hasDefaultWindowing_ = false; + } + + if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) + { + switch (imageInformation_.GetBitsStored()) + { + case 16: + expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; + break; + + case 32: + expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale32; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } + } + else if (isColor_) + { + expectedPixelFormat_ = Orthanc::PixelFormat_RGB24; + } + else if (imageInformation_.IsSigned()) + { + expectedPixelFormat_ = Orthanc::PixelFormat_SignedGrayscale16; + } + else + { + expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; + } + } + + OrthancStone::CoordinateSystem3D GetFrameGeometry(unsigned int frame) const + { + if (frame == 0) + { + return geometry_; + } + else if (frame >= imageInformation_.GetNumberOfFrames()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) + { + if (frame >= frameOffsets_.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + return OrthancStone::CoordinateSystem3D( + geometry_.GetOrigin() + frameOffsets_[frame] * geometry_.GetNormal(), + geometry_.GetAxisX(), + geometry_.GetAxisY()); + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } + } + + // TODO - Is this necessary? + bool FrameContainsPlane(unsigned int frame, + const OrthancStone::CoordinateSystem3D& plane) const + { + if (frame >= imageInformation_.GetNumberOfFrames()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + OrthancStone::CoordinateSystem3D tmp = geometry_; + + if (frame != 0) + { + tmp = GetFrameGeometry(frame); + } + + double distance; + + return (OrthancStone::CoordinateSystem3D::GetDistance(distance, tmp, plane) && + distance <= thickness_ / 2.0); + } + + + void ApplyRescale(Orthanc::ImageAccessor& image, + bool useDouble) const + { + if (image.GetFormat() != Orthanc::PixelFormat_Float32) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); + } + + if (hasRescale_) + { + const unsigned int width = image.GetWidth(); + const unsigned int height = image.GetHeight(); + + for (unsigned int y = 0; y < height; y++) + { + float* p = reinterpret_cast<float*>(image.GetRow(y)); + + if (useDouble) + { + // Slower, accurate implementation using double + for (unsigned int x = 0; x < width; x++, p++) + { + double value = static_cast<double>(*p); + *p = static_cast<float>(value * rescaleSlope_ + rescaleIntercept_); + } + } + else + { + // Fast, approximate implementation using float + for (unsigned int x = 0; x < width; x++, p++) + { + *p = (*p) * static_cast<float>(rescaleSlope_) + static_cast<float>(rescaleIntercept_); + } + } + } + } + } + }; + + + Data data_; + + + public: + DicomInstanceParameters(const DicomInstanceParameters& other) : + data_(other.data_) + { + } + + DicomInstanceParameters(const Orthanc::DicomMap& dicom) : + data_(dicom) + { + } + + void SetOrthancInstanceIdentifier(const std::string& id) + { + data_.orthancInstanceId_ = id; + } + + const std::string& GetOrthancInstanceIdentifier() const + { + return data_.orthancInstanceId_; + } + + const Orthanc::DicomImageInformation& GetImageInformation() const + { + return data_.imageInformation_; + } + + const std::string& GetStudyInstanceUid() const + { + return data_.studyInstanceUid_; + } + + const std::string& GetSeriesInstanceUid() const + { + return data_.seriesInstanceUid_; + } + + const std::string& GetSopInstanceUid() const + { + return data_.sopInstanceUid_; + } + + OrthancStone::SopClassUid GetSopClassUid() const + { + return data_.sopClassUid_; + } + + double GetThickness() const + { + return data_.thickness_; + } + + double GetPixelSpacingX() const + { + return data_.pixelSpacingX_; + } + + double GetPixelSpacingY() const + { + return data_.pixelSpacingY_; + } + + const OrthancStone::CoordinateSystem3D& GetGeometry() const + { + return data_.geometry_; + } + + OrthancStone::CoordinateSystem3D GetFrameGeometry(unsigned int frame) const + { + return data_.GetFrameGeometry(frame); + } + + // TODO - Is this necessary? + bool FrameContainsPlane(unsigned int frame, + const OrthancStone::CoordinateSystem3D& plane) const + { + return data_.FrameContainsPlane(frame, plane); + } + + bool IsColor() const + { + return data_.isColor_; + } + + bool HasRescale() const + { + return data_.hasRescale_; + } + + double GetRescaleIntercept() const + { + if (data_.hasRescale_) + { + return data_.rescaleIntercept_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + double GetRescaleSlope() const + { + if (data_.hasRescale_) + { + return data_.rescaleSlope_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + bool HasDefaultWindowing() const + { + return data_.hasDefaultWindowing_; + } + + float GetDefaultWindowingCenter() const + { + if (data_.hasDefaultWindowing_) + { + return data_.defaultWindowingCenter_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + float GetDefaultWindowingWidth() const + { + if (data_.hasDefaultWindowing_) + { + return data_.defaultWindowingWidth_; + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + } + + Orthanc::PixelFormat GetExpectedPixelFormat() const + { + return data_.expectedPixelFormat_; + } + + + OrthancStone::TextureBaseSceneLayer* CreateTexture(const Orthanc::ImageAccessor& source) const + { + assert(sizeof(float) == 4); + + Orthanc::PixelFormat sourceFormat = source.GetFormat(); + + if (sourceFormat != GetExpectedPixelFormat()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); + } + + if (sourceFormat == Orthanc::PixelFormat_RGB24) + { + // This is the case of a color image. No conversion has to be done. + return new OrthancStone::ColorTextureSceneLayer(source); + } + else + { + if (sourceFormat != Orthanc::PixelFormat_Grayscale16 && + sourceFormat != Orthanc::PixelFormat_Grayscale32 && + sourceFormat != Orthanc::PixelFormat_SignedGrayscale16) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } + + std::auto_ptr<OrthancStone::FloatTextureSceneLayer> texture; + + { + // This is the case of a grayscale frame. Convert it to Float32. + std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, + source.GetWidth(), + source.GetHeight(), + false)); + Orthanc::ImageProcessing::Convert(*converted, source); + + // Correct rescale slope/intercept if need be + data_.ApplyRescale(*converted, (sourceFormat == Orthanc::PixelFormat_Grayscale32)); + + texture.reset(new OrthancStone::FloatTextureSceneLayer(*converted)); + } + + if (data_.hasDefaultWindowing_) + { + texture->SetCustomWindowing(data_.defaultWindowingCenter_, + data_.defaultWindowingWidth_); + } + + return texture.release(); + } + } + }; + + + class DicomVolumeImage : public boost::noncopyable + { + private: + std::auto_ptr<OrthancStone::ImageBuffer3D> image_; + std::vector<DicomInstanceParameters*> slices_; + uint64_t revision_; + std::vector<uint64_t> slicesRevision_; + std::vector<unsigned int> slicesQuality_; + + void CheckSlice(size_t index, + const DicomInstanceParameters& reference) const + { + const DicomInstanceParameters& slice = *slices_[index]; + + if (!OrthancStone::GeometryToolbox::IsParallel( + reference.GetGeometry().GetNormal(), + slice.GetGeometry().GetNormal())) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, + "A slice in the volume image is not parallel to the others"); + } + + if (reference.GetExpectedPixelFormat() != slice.GetExpectedPixelFormat()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, + "The pixel format changes across the slices of the volume image"); + } + + if (reference.GetImageInformation().GetWidth() != slice.GetImageInformation().GetWidth() || + reference.GetImageInformation().GetHeight() != slice.GetImageInformation().GetHeight()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize, + "The width/height of slices are not constant in the volume image"); + } + + if (!OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingX(), slice.GetPixelSpacingX()) || + !OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingY(), slice.GetPixelSpacingY())) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, + "The pixel spacing of the slices change across the volume image"); + } + } + + + void CheckVolume() const + { + for (size_t i = 0; i < slices_.size(); i++) + { + assert(slices_[i] != NULL); + if (slices_[i]->GetImageInformation().GetNumberOfFrames() != 1) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, + "This class does not support multi-frame images"); + } + } + + if (slices_.size() != 0) + { + const DicomInstanceParameters& reference = *slices_[0]; + + for (size_t i = 1; i < slices_.size(); i++) + { + CheckSlice(i, reference); + } + } + } + + + void Clear() + { + image_.reset(); + + for (size_t i = 0; i < slices_.size(); i++) + { + assert(slices_[i] != NULL); + delete slices_[i]; + } + + slices_.clear(); + slicesRevision_.clear(); + slicesQuality_.clear(); + } + + + void CheckSliceIndex(size_t index) const + { + assert(slices_.size() == image_->GetDepth() && + slices_.size() == slicesRevision_.size()); + + if (!HasGeometry()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else if (index >= slices_.size()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + public: + DicomVolumeImage() + { + } + + ~DicomVolumeImage() + { + Clear(); + } + + // WARNING: The payload of "slices" must be of class "DicomInstanceParameters" + void SetGeometry(OrthancStone::SlicesSorter& slices) + { + Clear(); + + if (!slices.Sort()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, + "Cannot sort the 3D slices of a DICOM series"); + } + + if (slices.GetSlicesCount() == 0) + { + // Empty volume + image_.reset(new OrthancStone::ImageBuffer3D(Orthanc::PixelFormat_Grayscale8, 0, 0, 0, + false /* don't compute range */)); + } + else + { + slices_.reserve(slices.GetSlicesCount()); + slicesRevision_.resize(slices.GetSlicesCount(), 0); + slicesQuality_.resize(slices.GetSlicesCount(), 0); + + for (size_t i = 0; i < slices.GetSlicesCount(); i++) + { + const DicomInstanceParameters& slice = + dynamic_cast<const DicomInstanceParameters&>(slices.GetSlicePayload(i)); + slices_.push_back(new DicomInstanceParameters(slice)); + } + + CheckVolume(); + + const double spacingZ = slices.ComputeSpacingBetweenSlices(); + LOG(INFO) << "Computed spacing between slices: " << spacingZ << "mm"; + + const DicomInstanceParameters& parameters = *slices_[0]; + + image_.reset(new OrthancStone::ImageBuffer3D(parameters.GetExpectedPixelFormat(), + parameters.GetImageInformation().GetWidth(), + parameters.GetImageInformation().GetHeight(), + slices.GetSlicesCount(), false /* don't compute range */)); + + image_->GetGeometry().SetAxialGeometry(slices.GetSliceGeometry(0)); + image_->GetGeometry().SetVoxelDimensions(parameters.GetPixelSpacingX(), + parameters.GetPixelSpacingY(), spacingZ); + } + + image_->Clear(); + + revision_++; + } + + uint64_t GetRevision() const + { + return revision_; + } + + bool HasGeometry() const + { + return (image_.get() != NULL); + } + + const OrthancStone::ImageBuffer3D& GetImage() const + { + if (!HasGeometry()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + return *image_; + } + } + + size_t GetSlicesCount() const + { + if (!HasGeometry()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + return slices_.size(); + } + } + + const DicomInstanceParameters& GetSliceParameters(size_t index) const + { + CheckSliceIndex(index); + return *slices_[index]; + } + + uint64_t GetSliceRevision(size_t index) const + { + CheckSliceIndex(index); + return slicesRevision_[index]; + } + + void SetSliceContent(size_t index, + const Orthanc::ImageAccessor& image, + unsigned int quality) + { + CheckSliceIndex(index); + + // If a better image quality is already available, don't update the content + if (quality >= slicesQuality_[index]) + { + { + OrthancStone::ImageBuffer3D::SliceWriter writer + (*image_, OrthancStone::VolumeProjection_Axial, index); + Orthanc::ImageProcessing::Copy(writer.GetAccessor(), image); + } + + revision_ ++; + slicesRevision_[index] += 1; + } + } + }; + + + + class IDicomVolumeSource : public boost::noncopyable + { + public: + virtual ~IDicomVolumeSource() + { + } + + virtual const DicomVolumeImage& GetVolume() const = 0; + + virtual void NotifyAxialSliceAccessed(unsigned int sliceIndex) = 0; + }; + + + + class VolumeSeriesOrthancLoader : + public OrthancStone::IObserver, + public IDicomVolumeSource + { + private: + static const unsigned int LOW_QUALITY = 0; + static const unsigned int MIDDLE_QUALITY = 1; + static const unsigned int BEST_QUALITY = 2; + + + static unsigned int GetSliceIndexPayload(const OracleCommandWithPayload& command) + { + return dynamic_cast< const Orthanc::SingleValueObject<unsigned int>& >(command.GetPayload()).GetValue(); + } + + + void ScheduleNextSliceDownload() + { + assert(strategy_.get() != NULL); + + unsigned int sliceIndex, quality; + + if (strategy_->GetNext(sliceIndex, quality)) + { + assert(quality <= BEST_QUALITY); + + const DicomInstanceParameters& slice = volume_.GetSliceParameters(sliceIndex); + + const std::string& instance = slice.GetOrthancInstanceIdentifier(); + if (instance.empty()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + std::auto_ptr<Refactoring::OracleCommandWithPayload> command; + + if (quality == BEST_QUALITY) + { + std::auto_ptr<Refactoring::GetOrthancImageCommand> tmp( + new Refactoring::GetOrthancImageCommand); + tmp->SetHttpHeader("Accept-Encoding", "gzip"); + tmp->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam))); + tmp->SetInstanceUri(instance, slice.GetExpectedPixelFormat()); + tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); + command.reset(tmp.release()); + } + else + { + std::auto_ptr<Refactoring::GetOrthancWebViewerJpegCommand> tmp( + new Refactoring::GetOrthancWebViewerJpegCommand); + tmp->SetHttpHeader("Accept-Encoding", "gzip"); + tmp->SetInstance(instance); + tmp->SetQuality((quality == 0 ? 50 : 90)); + tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); + command.reset(tmp.release()); + } + + command->SetPayload(new Orthanc::SingleValueObject<unsigned int>(sliceIndex)); + oracle_.Schedule(*this, command.release()); + } + } + + + void LoadGeometry(const OrthancRestApiCommand::SuccessMessage& message) + { + Json::Value body; + message.ParseJsonBody(body); + + if (body.type() != Json::objectValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); + } + + { + Json::Value::Members instances = body.getMemberNames(); + + OrthancStone::SlicesSorter slices; + + for (size_t i = 0; i < instances.size(); i++) + { + Orthanc::DicomMap dicom; + dicom.FromDicomAsJson(body[instances[i]]); + + std::auto_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(dicom)); + instance->SetOrthancInstanceIdentifier(instances[i]); + + OrthancStone::CoordinateSystem3D geometry = instance->GetGeometry(); + slices.AddSlice(geometry, instance.release()); + } + + volume_.SetGeometry(slices); + } + + if (volume_.GetSlicesCount() != 0) + { + strategy_.reset(new OrthancStone::BasicFetchingStrategy( + new OrthancStone::BasicFetchingItemsSorter(volume_.GetSlicesCount()), BEST_QUALITY)); + + for (unsigned int i = 0; i < 4; i++) // Schedule up to 4 simultaneous downloads (TODO - parameter) + { + ScheduleNextSliceDownload(); + } + } + } + + + void LoadBestQualitySliceContent(const Refactoring::GetOrthancImageCommand::SuccessMessage& message) + { + volume_.SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), + message.GetImage(), BEST_QUALITY); + + ScheduleNextSliceDownload(); + } + + + void LoadJpegSliceContent(const Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage& message) + { + unsigned int quality; + + switch (message.GetOrigin().GetQuality()) + { + case 50: + quality = LOW_QUALITY; + break; + + case 90: + quality = MIDDLE_QUALITY; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + volume_.SetSliceContent(GetSliceIndexPayload(message.GetOrigin()), message.GetImage(), quality); + + ScheduleNextSliceDownload(); + } + + + IOracle& oracle_; + bool active_; + DicomVolumeImage volume_; + + std::auto_ptr<OrthancStone::IFetchingStrategy> strategy_; + + public: + VolumeSeriesOrthancLoader(IOracle& oracle, + OrthancStone::IObservable& oracleObservable) : + IObserver(oracleObservable.GetBroker()), + oracle_(oracle), + active_(false) + { + oracleObservable.RegisterObserverCallback( + new OrthancStone::Callable<VolumeSeriesOrthancLoader, OrthancRestApiCommand::SuccessMessage> + (*this, &VolumeSeriesOrthancLoader::LoadGeometry)); + + oracleObservable.RegisterObserverCallback( + new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancImageCommand::SuccessMessage> + (*this, &VolumeSeriesOrthancLoader::LoadBestQualitySliceContent)); + + oracleObservable.RegisterObserverCallback( + new OrthancStone::Callable<VolumeSeriesOrthancLoader, GetOrthancWebViewerJpegCommand::SuccessMessage> + (*this, &VolumeSeriesOrthancLoader::LoadJpegSliceContent)); + } + + void LoadSeries(const std::string& seriesId) + { + if (active_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + active_ = true; + + std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand); + command->SetUri("/series/" + seriesId + "/instances-tags"); + + oracle_.Schedule(*this, command.release()); + } + + + virtual const DicomVolumeImage& GetVolume() const + { + return volume_; + } + + + virtual void NotifyAxialSliceAccessed(unsigned int sliceIndex) + { + if (strategy_.get() == NULL) + { + // Should have called GetVolume().HasGeometry() before + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + strategy_->SetCurrent(sliceIndex); + } + } + }; + + + +#if 0 + void LoadInstance(const std::string& instanceId) + { + if (active_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + active_ = true; + + // Tag "3004-000c" is "Grid Frame Offset Vector", which is + // mandatory to read RT DOSE, but is too long to be returned by default + + // TODO => Should be part of a second call if needed + + std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand); + command->SetUri("/instances/" + instanceId + "/tags?ignore-length=3004-000c"); + command->SetPayload(new LoadInstanceGeometryHandler(*this)); + + oracle_.Schedule(*this, command.release()); + } +#endif + + + /* class VolumeSlicerBase : public IVolumeSlicer + { + private: + OrthancStone::Scene2D& scene_; + int layerDepth_; + bool first_; + OrthancStone::CoordinateSystem3D lastPlane_; + + protected: + bool HasViewportPlaneChanged(const OrthancStone::CoordinateSystem3D& plane) const + { + if (first_ || + !OrthancStone::LinearAlgebra::IsCloseToZero( + boost::numeric::ublas::norm_2(lastPlane_.GetNormal() - plane.GetNormal()))) + { + // This is the first rendering, or the plane has not the same orientation + return false; + } + else + { + double offset1 = lastPlane_.ProjectAlongNormal(plane.GetOrigin()); + double offset2 = lastPlane_.ProjectAlongNormal(lastPlane_.GetOrigin()); + return OrthancStone::LinearAlgebra::IsCloseToZero(offset2 - offset1); + } + } + + void SetLastViewportPlane(const OrthancStone::CoordinateSystem3D& plane) + { + first_ = false; + lastPlane_ = plane; + } + + void SetLayer(OrthancStone::ISceneLayer* layer) + { + scene_.SetLayer(layerDepth_, layer); + } + + void DeleteLayer() + { + scene_.DeleteLayer(layerDepth_); + } + + public: + VolumeSlicerBase(OrthancStone::Scene2D& scene, + int layerDepth) : + scene_(scene), + layerDepth_(layerDepth), + first_(true) + { + } + };*/ + + + + class DicomVolumeMPRSlicer : public IVolumeSlicer + { + private: + bool linearInterpolation_; + OrthancStone::Scene2D& scene_; + int layerDepth_; + IDicomVolumeSource& source_; + bool first_; + OrthancStone::VolumeProjection lastProjection_; + unsigned int lastSliceIndex_; + uint64_t lastSliceRevision_; + + public: + DicomVolumeMPRSlicer(OrthancStone::Scene2D& scene, + int layerDepth, + IDicomVolumeSource& source) : + linearInterpolation_(false), + scene_(scene), + layerDepth_(layerDepth), + source_(source), + first_(true) + { + } + + void SetLinearInterpolation(bool enabled) + { + linearInterpolation_ = enabled; + } + + bool IsLinearInterpolation() const + { + return linearInterpolation_; + } + + virtual void SetViewportPlane(const OrthancStone::CoordinateSystem3D& plane) + { + if (!source_.GetVolume().HasGeometry() || + source_.GetVolume().GetSlicesCount() == 0) + { + scene_.DeleteLayer(layerDepth_); + return; + } + + const OrthancStone::VolumeImageGeometry& geometry = source_.GetVolume().GetImage().GetGeometry(); + + OrthancStone::VolumeProjection projection; + unsigned int sliceIndex; + if (!geometry.DetectSlice(projection, sliceIndex, plane)) + { + // The cutting plane is neither axial, nor coronal, nor + // sagittal. Could use "VolumeReslicer" here. + scene_.DeleteLayer(layerDepth_); + return; + } + + uint64_t sliceRevision; + if (projection == OrthancStone::VolumeProjection_Axial) + { + sliceRevision = source_.GetVolume().GetSliceRevision(sliceIndex); + + if (first_ || + lastSliceIndex_ != sliceIndex) + { + // Reorder the prefetching queue + source_.NotifyAxialSliceAccessed(sliceIndex); + } + } + else + { + // For coronal and sagittal projections, we take the global + // revision of the volume + sliceRevision = source_.GetVolume().GetRevision(); + } + + if (first_ || + lastProjection_ != projection || + lastSliceIndex_ != sliceIndex || + lastSliceRevision_ != sliceRevision) + { + // Either the viewport plane, or the content of the slice have not + // changed since the last time the layer was set: Update is needed + + first_ = false; + lastProjection_ = projection; + lastSliceIndex_ = sliceIndex; + lastSliceRevision_ = sliceRevision; + + std::auto_ptr<OrthancStone::TextureBaseSceneLayer> texture; + + { + const DicomInstanceParameters& parameters = source_.GetVolume().GetSliceParameters + (projection == OrthancStone::VolumeProjection_Axial ? sliceIndex : 0); + + OrthancStone::ImageBuffer3D::SliceReader reader(source_.GetVolume().GetImage(), projection, sliceIndex); + texture.reset(parameters.CreateTexture(reader.GetAccessor())); + } + + const OrthancStone::CoordinateSystem3D& system = geometry.GetProjectionGeometry(projection); + + double x0, y0, x1, y1; + system.ProjectPoint(x0, y0, system.GetOrigin()); + system.ProjectPoint(x0, y0, system.GetOrigin() + system.GetAxisX()); + texture->SetOrigin(x0, y0); + + double dx = x1 - x0; + double dy = y1 - y0; + if (!OrthancStone::LinearAlgebra::IsCloseToZero(dx) || + !OrthancStone::LinearAlgebra::IsCloseToZero(dy)) + { + texture->SetAngle(atan2(dy, dx)); + } + + OrthancStone::Vector tmp; + geometry.GetVoxelDimensions(projection); + texture->SetPixelSpacing(tmp[0], tmp[1]); + + texture->SetLinearInterpolation(linearInterpolation_); + + scene_.SetLayer(layerDepth_, texture.release()); + } + } + }; + + + + + class NativeOracle : public IOracle { private: @@ -992,7 +2176,7 @@ public: NativeOracle(IMessageEmitter& emitter) : - emitter_(emitter), + emitter_(emitter), state_(State_Setup), workers_(4) { @@ -1067,7 +2251,6 @@ }; - class NativeApplicationContext : public IMessageEmitter { private: @@ -1105,8 +2288,8 @@ public: ReaderLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) + that_(that), + lock_(that.mutex_) { } }; @@ -1120,8 +2303,8 @@ public: WriterLock(NativeApplicationContext& that) : - that_(that), - lock_(that.mutex_) + that_(that), + lock_(that.mutex_) { } @@ -1136,638 +2319,6 @@ } }; }; - - - - class DicomInstanceParameters : - public Orthanc::IDynamicObject /* to be used as a payload of SlicesSorter */ - { - private: - struct Data // Struct to ease the copy constructor - { - Orthanc::DicomImageInformation imageInformation_; - OrthancStone::SopClassUid sopClassUid_; - double thickness_; - double pixelSpacingX_; - double pixelSpacingY_; - OrthancStone::CoordinateSystem3D geometry_; - OrthancStone::Vector frameOffsets_; - bool isColor_; - bool hasRescale_; - double rescaleOffset_; - double rescaleSlope_; - bool hasDefaultWindowing_; - float defaultWindowingCenter_; - float defaultWindowingWidth_; - Orthanc::PixelFormat expectedPixelFormat_; - - void ComputeDoseOffsets(const Orthanc::DicomMap& dicom) - { - // http://dicom.nema.org/medical/Dicom/2016a/output/chtml/part03/sect_C.8.8.3.2.html - - { - std::string increment; - - if (dicom.CopyToString(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) - { - Orthanc::Toolbox::ToUpperCase(increment); - if (increment != "3004,000C") // This is the "Grid Frame Offset Vector" tag - { - LOG(ERROR) << "RT-DOSE: Bad value for the \"FrameIncrementPointer\" tag"; - return; - } - } - } - - if (!OrthancStone::LinearAlgebra::ParseVector(frameOffsets_, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) || - frameOffsets_.size() < imageInformation_.GetNumberOfFrames()) - { - LOG(ERROR) << "RT-DOSE: No information about the 3D location of some slice(s)"; - frameOffsets_.clear(); - } - else - { - if (frameOffsets_.size() >= 2) - { - thickness_ = frameOffsets_[1] - frameOffsets_[0]; - - if (thickness_ < 0) - { - thickness_ = -thickness_; - } - } - } - } - - Data(const Orthanc::DicomMap& dicom) : - imageInformation_(dicom) - { - if (imageInformation_.GetNumberOfFrames() <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - - std::string s; - if (!dicom.CopyToString(s, Orthanc::DICOM_TAG_SOP_CLASS_UID, false)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); - } - else - { - sopClassUid_ = OrthancStone::StringToSopClassUid(s); - } - - if (!dicom.ParseDouble(thickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS)) - { - thickness_ = 100.0 * std::numeric_limits<double>::epsilon(); - } - - OrthancStone::GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom); - - std::string position, orientation; - if (dicom.CopyToString(position, Orthanc::DICOM_TAG_IMAGE_POSITION_PATIENT, false) && - dicom.CopyToString(orientation, Orthanc::DICOM_TAG_IMAGE_ORIENTATION_PATIENT, false)) - { - geometry_ = OrthancStone::CoordinateSystem3D(position, orientation); - } - - if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) - { - ComputeDoseOffsets(dicom); - } - - isColor_ = (imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome1 && - imageInformation_.GetPhotometricInterpretation() != Orthanc::PhotometricInterpretation_Monochrome2); - - double doseGridScaling; - - if (dicom.ParseDouble(rescaleOffset_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && - dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) - { - hasRescale_ = true; - } - else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) - { - hasRescale_ = true; - rescaleOffset_ = 0; - rescaleSlope_ = doseGridScaling; - } - else - { - hasRescale_ = false; - } - - OrthancStone::Vector c, w; - if (OrthancStone::LinearAlgebra::ParseVector(c, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && - OrthancStone::LinearAlgebra::ParseVector(w, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH) && - c.size() > 0 && - w.size() > 0) - { - hasDefaultWindowing_ = true; - defaultWindowingCenter_ = static_cast<float>(c[0]); - defaultWindowingWidth_ = static_cast<float>(w[0]); - } - else - { - hasDefaultWindowing_ = false; - } - - if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) - { - switch (imageInformation_.GetBitsStored()) - { - case 16: - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; - break; - - case 32: - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale32; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } - else if (isColor_) - { - expectedPixelFormat_ = Orthanc::PixelFormat_RGB24; - } - else if (imageInformation_.IsSigned()) - { - expectedPixelFormat_ = Orthanc::PixelFormat_SignedGrayscale16; - } - else - { - expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; - } - } - - OrthancStone::CoordinateSystem3D GetFrameGeometry(unsigned int frame) const - { - if (frame == 0) - { - return geometry_; - } - else if (frame >= imageInformation_.GetNumberOfFrames()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else if (sopClassUid_ == OrthancStone::SopClassUid_RTDose) - { - if (frame >= frameOffsets_.size()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - - return OrthancStone::CoordinateSystem3D( - geometry_.GetOrigin() + frameOffsets_[frame] * geometry_.GetNormal(), - geometry_.GetAxisX(), - geometry_.GetAxisY()); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } - } - - // TODO - Is this necessary? - bool FrameContainsPlane(unsigned int frame, - const OrthancStone::CoordinateSystem3D& plane) const - { - if (frame >= imageInformation_.GetNumberOfFrames()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - OrthancStone::CoordinateSystem3D tmp = geometry_; - - if (frame != 0) - { - tmp = GetFrameGeometry(frame); - } - - double distance; - - return (OrthancStone::CoordinateSystem3D::GetDistance(distance, tmp, plane) && - distance <= thickness_ / 2.0); - } - }; - - Data data_; - - - public: - DicomInstanceParameters(const DicomInstanceParameters& other) : - data_(other.data_) - { - } - - - DicomInstanceParameters(const Orthanc::DicomMap& dicom) : - data_(dicom) - { - } - - const Orthanc::DicomImageInformation& GetImageInformation() const - { - return data_.imageInformation_; - } - - OrthancStone::SopClassUid GetSopClassUid() const - { - return data_.sopClassUid_; - } - - double GetThickness() const - { - return data_.thickness_; - } - - double GetPixelSpacingX() const - { - return data_.pixelSpacingX_; - } - - double GetPixelSpacingY() const - { - return data_.pixelSpacingY_; - } - - const OrthancStone::CoordinateSystem3D& GetGeometry() const - { - return data_.geometry_; - } - - OrthancStone::CoordinateSystem3D GetFrameGeometry(unsigned int frame) const - { - return data_.GetFrameGeometry(frame); - } - - // TODO - Is this necessary? - bool FrameContainsPlane(unsigned int frame, - const OrthancStone::CoordinateSystem3D& plane) const - { - return data_.FrameContainsPlane(frame, plane); - } - - bool IsColor() const - { - return data_.isColor_; - } - - bool HasRescale() const - { - return data_.hasRescale_; - } - - double GetRescaleOffset() const - { - if (data_.hasRescale_) - { - return data_.rescaleOffset_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - double GetRescaleSlope() const - { - if (data_.hasRescale_) - { - return data_.rescaleSlope_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - bool HasDefaultWindowing() const - { - return data_.hasDefaultWindowing_; - } - - float GetDefaultWindowingCenter() const - { - if (data_.hasDefaultWindowing_) - { - return data_.defaultWindowingCenter_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - float GetDefaultWindowingWidth() const - { - if (data_.hasDefaultWindowing_) - { - return data_.defaultWindowingWidth_; - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - } - - Orthanc::PixelFormat GetExpectedPixelFormat() const - { - return data_.expectedPixelFormat_; - } - }; - - - class DicomVolumeImage : public boost::noncopyable - { - private: - std::auto_ptr<OrthancStone::ImageBuffer3D> image_; - std::vector<DicomInstanceParameters*> slices_; - - static const DicomInstanceParameters& - GetSliceParameters(const OrthancStone::SlicesSorter& slices, - size_t index) - { - return dynamic_cast<const DicomInstanceParameters&>(slices.GetSlicePayload(index)); - } - - static void CheckSlice(const OrthancStone::SlicesSorter& slices, - size_t index, - const OrthancStone::CoordinateSystem3D& reference, - const DicomInstanceParameters& a) - { - const OrthancStone::CoordinateSystem3D& slice = slices.GetSliceGeometry(index); - const DicomInstanceParameters& b = GetSliceParameters(slices, index); - - if (!OrthancStone::GeometryToolbox::IsParallel(reference.GetNormal(), slice.GetNormal())) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, - "A slice in the volume image is not parallel to the others"); - } - - if (a.GetExpectedPixelFormat() != b.GetExpectedPixelFormat()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, - "The pixel format changes across the slices of the volume image"); - } - - if (a.GetImageInformation().GetWidth() != b.GetImageInformation().GetWidth() || - a.GetImageInformation().GetHeight() != b.GetImageInformation().GetHeight()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize, - "The width/height of slices are not constant in the volume image"); - } - - if (!OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || - !OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, - "The pixel spacing of the slices change across the volume image"); - } - } - - - static void CheckVolume(const OrthancStone::SlicesSorter& slices) - { - for (size_t i = 0; i < slices.GetSlicesCount(); i++) - { - if (GetSliceParameters(slices, i).GetImageInformation().GetNumberOfFrames() != 1) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, - "This class does not support multi-frame images"); - } - } - - if (slices.GetSlicesCount() != 0) - { - const OrthancStone::CoordinateSystem3D& reference = slices.GetSliceGeometry(0); - const DicomInstanceParameters& dicom = GetSliceParameters(slices, 0); - - for (size_t i = 1; i < slices.GetSlicesCount(); i++) - { - CheckSlice(slices, i, reference, dicom); - } - } - } - - - void Clear() - { - image_.reset(); - - for (size_t i = 0; i < slices_.size(); i++) - { - assert(slices_[i] != NULL); - delete slices_[i]; - } - } - - - public: - DicomVolumeImage() - { - } - - ~DicomVolumeImage() - { - Clear(); - } - - // WARNING: The payload of "slices" must be of class "DicomInstanceParameters" - void SetGeometry(OrthancStone::SlicesSorter& slices) - { - Clear(); - - if (!slices.Sort()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, - "Cannot sort the 3D slices of a DICOM series"); - } - - slices_.reserve(slices.GetSlicesCount()); - - for (size_t i = 0; i < slices.GetSlicesCount(); i++) - { - slices_.push_back(new DicomInstanceParameters(GetSliceParameters(slices, i))); - } - - CheckVolume(slices); - - const double spacingZ = slices.ComputeSpacingBetweenSlices(); - LOG(INFO) << "Computed spacing between slices: " << spacingZ << "mm"; - - const DicomInstanceParameters& parameters = GetSliceParameters(slices, 0); - - image_.reset(new OrthancStone::ImageBuffer3D(parameters.GetExpectedPixelFormat(), - parameters.GetImageInformation().GetWidth(), - parameters.GetImageInformation().GetHeight(), - slices.GetSlicesCount(), false /* don't compute range */)); - - image_->SetAxialGeometry(slices.GetSliceGeometry(0)); - image_->SetVoxelDimensions(parameters.GetPixelSpacingX(), parameters.GetPixelSpacingY(), spacingZ); - image_->Clear(); - } - - bool IsGeometryReady() const - { - return (image_.get() != NULL); - } - - const OrthancStone::ImageBuffer3D& GetImage() const - { - if (!IsGeometryReady()) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - return *image_; - } - } - }; - - - - class AxialVolumeOrthancLoader : public OrthancStone::IObserver - { - private: - class MessageHandler : public Orthanc::IDynamicObject - { - public: - virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const = 0; - }; - - void Handle(const OrthancRestApiCommand::SuccessMessage& message) - { - dynamic_cast<const MessageHandler&>(message.GetOrigin().GetPayload()).Handle(message); - } - - - class LoadSeriesGeometryHandler : public MessageHandler - { - private: - AxialVolumeOrthancLoader& that_; - - public: - LoadSeriesGeometryHandler(AxialVolumeOrthancLoader& that) : - that_(that) - { - } - - virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const - { - Json::Value value; - message.ParseJsonBody(value); - - if (value.type() != Json::objectValue) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - Json::Value::Members instances = value.getMemberNames(); - - OrthancStone::SlicesSorter slices; - - for (size_t i = 0; i < instances.size(); i++) - { - Orthanc::DicomMap dicom; - dicom.FromDicomAsJson(value[instances[i]]); - - std::auto_ptr<DicomInstanceParameters> instance(new DicomInstanceParameters(dicom)); - - OrthancStone::CoordinateSystem3D geometry = instance->GetGeometry(); - slices.AddSlice(geometry, instance.release()); - } - - that_.image_.SetGeometry(slices); - } - }; - - - class LoadInstanceGeometryHandler : public MessageHandler - { - private: - AxialVolumeOrthancLoader& that_; - - public: - LoadInstanceGeometryHandler(AxialVolumeOrthancLoader& that) : - that_(that) - { - } - - virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const - { - Json::Value value; - message.ParseJsonBody(value); - - if (value.type() != Json::objectValue) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - - Orthanc::DicomMap dicom; - dicom.FromDicomAsJson(value); - - DicomInstanceParameters instance(dicom); - } - }; - - - bool active_; - DicomVolumeImage image_; - - public: - AxialVolumeOrthancLoader(OrthancStone::IObservable& oracle) : - IObserver(oracle.GetBroker()), - active_(false) - { - oracle.RegisterObserverCallback( - new OrthancStone::Callable<AxialVolumeOrthancLoader, OrthancRestApiCommand::SuccessMessage> - (*this, &AxialVolumeOrthancLoader::Handle)); - } - - void LoadSeries(IOracle& oracle, - const std::string& seriesId) - { - if (active_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - active_ = true; - - std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand); - command->SetUri("/series/" + seriesId + "/instances-tags"); - command->SetPayload(new LoadSeriesGeometryHandler(*this)); - - oracle.Schedule(*this, command.release()); - } - - void LoadInstance(IOracle& oracle, - const std::string& instanceId) - { - if (active_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - active_ = true; - - // Tag "3004-000c" is "Grid Frame Offset Vector", which is - // mandatory to read RT DOSE, but is too long to be returned by default - - // TODO => Should be part of a second call if needed - - std::auto_ptr<Refactoring::OrthancRestApiCommand> command(new Refactoring::OrthancRestApiCommand); - command->SetUri("/instances/" + instanceId + "/tags?ignore-length=3004-000c"); - command->SetPayload(new LoadInstanceGeometryHandler(*this)); - - oracle.Schedule(*this, command.release()); - } - }; - } @@ -1823,7 +2374,7 @@ oracle.RegisterObserverCallback (new OrthancStone::Callable - <Toto, Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle)); + <Toto, Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle)); oracle.RegisterObserverCallback (new OrthancStone::Callable @@ -1832,29 +2383,19 @@ }; -void Run(Refactoring::NativeApplicationContext& context) +void Run(Refactoring::NativeApplicationContext& context, + Refactoring::IOracle& oracle) { std::auto_ptr<Toto> toto; - std::auto_ptr<Refactoring::AxialVolumeOrthancLoader> loader1, loader2; + std::auto_ptr<Refactoring::VolumeSeriesOrthancLoader> loader1, loader2; { Refactoring::NativeApplicationContext::WriterLock lock(context); toto.reset(new Toto(lock.GetOracleObservable())); - loader1.reset(new Refactoring::AxialVolumeOrthancLoader(lock.GetOracleObservable())); - loader2.reset(new Refactoring::AxialVolumeOrthancLoader(lock.GetOracleObservable())); + loader1.reset(new Refactoring::VolumeSeriesOrthancLoader(oracle, lock.GetOracleObservable())); + loader2.reset(new Refactoring::VolumeSeriesOrthancLoader(oracle, lock.GetOracleObservable())); } - Refactoring::NativeOracle oracle(context); - - { - Orthanc::WebServiceParameters p; - //p.SetUrl("http://localhost:8043/"); - p.SetCredentials("orthanc", "orthanc"); - oracle.SetOrthancParameters(p); - } - - oracle.Start(); - if (1) { Json::Value v = Json::objectValue; @@ -1921,17 +2462,15 @@ // 2017-11-17-Anonymized - //loader1->LoadSeries(oracle, "cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT - loader2->LoadInstance(oracle, "41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE + //loader1->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT + //loader2->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE // Delphine - loader1->LoadSeries(oracle, "5990e39c-51e5f201-fe87a54c-31a55943-e59ef80e"); // CT + loader1->LoadSeries("5990e39c-51e5f201-fe87a54c-31a55943-e59ef80e"); // CT LOG(WARNING) << "...Waiting for Ctrl-C..."; Orthanc::SystemToolbox::ServerBarrier(); //boost::this_thread::sleep(boost::posix_time::seconds(1)); - - oracle.Stop(); } @@ -1949,7 +2488,21 @@ try { Refactoring::NativeApplicationContext context; - Run(context); + + Refactoring::NativeOracle oracle(context); + + { + Orthanc::WebServiceParameters p; + //p.SetUrl("http://localhost:8043/"); + p.SetCredentials("orthanc", "orthanc"); + oracle.SetOrthancParameters(p); + } + + oracle.Start(); + + Run(context, oracle); + + oracle.Stop(); } catch (Orthanc::OrthancException& e) {
--- a/Samples/Sdl/TrackerSampleApp.cpp Thu May 16 19:10:38 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Tue May 21 13:25:58 2019 +0200 @@ -20,21 +20,22 @@ #include "TrackerSampleApp.h" -#include "../Common/CreateLineMeasureTracker.h" -#include "../Common/CreateAngleMeasureTracker.h" - -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include <Framework/Scene2DViewport/CreateLineMeasureTracker.h> +#include <Framework/Scene2DViewport/CreateAngleMeasureTracker.h> -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/StoneInitialization.h" +#include <Framework/Scene2D/PanSceneTracker.h> +#include <Framework/Scene2D/RotateSceneTracker.h> +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ZoomSceneTracker.h> +#include <Framework/Scene2D/CairoCompositor.h> +#include <Framework/Scene2D/ColorTextureSceneLayer.h> +#include <Framework/Scene2D/OpenGLCompositor.h> - // From Orthanc framework +#include <Framework/StoneInitialization.h> + +#include <Applications/Sdl/SdlOpenGLWindow.h> + +// From Orthanc framework #include <Core/Logging.h> #include <Core/OrthancException.h> #include <Core/Images/Image.h> @@ -67,9 +68,9 @@ return descs[i]; } - Scene2D& TrackerSampleApp::GetScene() + Scene2DPtr TrackerSampleApp::GetScene() { - return scene_; + return controller_->GetScene(); } void TrackerSampleApp::SelectNextTool() @@ -87,17 +88,19 @@ return; std::stringstream msg; - for (auto kv : infoTextMap_) + + for (std::map<std::string, std::string>::const_iterator kv = infoTextMap_.begin(); + kv != infoTextMap_.end(); ++kv) { - msg << kv.first << " : " << kv.second << std::endl; + msg << kv->first << " : " << kv->second << std::endl; } - auto msgS = msg.str(); + std::string msgS = msg.str(); TextSceneLayer* layerP = NULL; - if (scene_.HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) + if (GetScene()->HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = dynamic_cast<TextSceneLayer&>( - scene_.GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); + GetScene()->GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); layerP = &layer; } else @@ -109,29 +112,29 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_TopLeft); //layer->SetPosition(0,0); - scene_.SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene()->SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); } // position the fixed info text in the upper right corner layerP->SetText(msgS.c_str()); double cX = compositor_->GetCanvasWidth() * (-0.5); double cY = compositor_->GetCanvasHeight() * (-0.5); - scene_.GetCanvasToSceneTransform().Apply(cX,cY); + GetScene()->GetCanvasToSceneTransform().Apply(cX,cY); layerP->SetPosition(cX, cY); } void TrackerSampleApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) { - ScenePoint2D p = e.GetMainPosition().Apply(scene_.GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()); char buf[128]; sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", p.GetX(), p.GetY(), e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); - if (scene_.HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) + if (GetScene()->HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = - dynamic_cast<TextSceneLayer&>(scene_.GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); + dynamic_cast<TextSceneLayer&>(GetScene()->GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } @@ -143,13 +146,13 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); - scene_.SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene()->SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); } } void TrackerSampleApp::HideInfoText() { - scene_.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); + GetScene()->DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); } void TrackerSampleApp::HandleApplicationEvent( @@ -191,8 +194,8 @@ // e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); activeTracker_->PointerMove(e); - if (!activeTracker_->IsActive()) - activeTracker_ = NULL; + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); } } } @@ -203,8 +206,8 @@ PointerEvent e; e.AddPosition(compositor_->GetPixelCenterCoordinates(event.button.x, event.button.y)); activeTracker_->PointerUp(e); - if (!activeTracker_->IsActive()) - activeTracker_ = NULL; + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); } } else if (event.type == SDL_MOUSEBUTTONDOWN) @@ -215,8 +218,8 @@ if (activeTracker_) { activeTracker_->PointerDown(e); - if (!activeTracker_->IsActive()) - activeTracker_ = NULL; + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); } else { @@ -233,8 +236,8 @@ if (activeTracker_) { activeTracker_->Cancel(); - if (!activeTracker_->IsActive()) - activeTracker_ = NULL; + if (!activeTracker_->IsAlive()) + activeTracker_.reset(); } break; @@ -249,7 +252,7 @@ break; case SDLK_s: - scene_.FitContent(compositor_->GetCanvasWidth(), + controller_->FitContent(compositor_->GetCanvasWidth(), compositor_->GetCanvasHeight()); break; @@ -267,7 +270,8 @@ } - void TrackerSampleApp::OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message) + void TrackerSampleApp::OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message) { DisplayInfoText(); } @@ -279,12 +283,12 @@ switch (event.button.button) { case SDL_BUTTON_MIDDLE: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new PanSceneTracker + (controller_, e)); case SDL_BUTTON_RIGHT: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + return FlexiblePointerTrackerPtr(new ZoomSceneTracker + (controller_, e, compositor_->GetCanvasHeight())); case SDL_BUTTON_LEFT: { @@ -309,50 +313,50 @@ { case GuiTool_Rotate: //LOG(TRACE) << "Creating RotateSceneTracker"; - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new RotateSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new RotateSceneTracker( + controller_, e)); case GuiTool_Pan: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new PanSceneTracker( + controller_, e)); case GuiTool_Zoom: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + return FlexiblePointerTrackerPtr(new ZoomSceneTracker( + controller_, e, compositor_->GetCanvasHeight())); //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new AngleMeasureTracker(GetScene(), e); //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new CircleMeasureTracker(GetScene(), e); //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new EllipseMeasureTracker(GetScene(), e); case GuiTool_LineMeasure: return FlexiblePointerTrackerPtr(new CreateLineMeasureTracker( - IObserver::GetBroker(), scene_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), controller_, e)); case GuiTool_AngleMeasure: return FlexiblePointerTrackerPtr(new CreateAngleMeasureTracker( - IObserver::GetBroker(), scene_, undoStack_, measureTools_, e)); - return NULL; + IObserver::GetBroker(), controller_, e)); case GuiTool_CircleMeasure: LOG(ERROR) << "Not implemented yet!"; - return NULL; + return FlexiblePointerTrackerPtr(); case GuiTool_EllipseMeasure: LOG(ERROR) << "Not implemented yet!"; - return NULL; + return FlexiblePointerTrackerPtr(); default: throw OrthancException(ErrorCode_InternalError, "Wrong tool!"); } } } default: - return NULL; + return FlexiblePointerTrackerPtr(); } } TrackerSampleApp::TrackerSampleApp(MessageBroker& broker) : IObserver(broker) - , scene_(broker) , currentTool_(GuiTool_Rotate) { - scene_.RegisterObserverCallback( - new Callable<TrackerSampleApp, Scene2D::SceneTransformChanged> + controller_ = ViewportControllerPtr(new ViewportController(broker)); + + controller_->RegisterObserverCallback( + new Callable<TrackerSampleApp, ViewportController::SceneTransformChanged> (*this, &TrackerSampleApp::OnSceneTransformChanged)); TEXTURE_2x2_1_ZINDEX = 1; @@ -362,8 +366,6 @@ LINESET_2_ZINDEX = 5; FLOATING_INFOTEXT_LAYER_ZINDEX = 6; FIXED_INFOTEXT_LAYER_ZINDEX = 7; - - } void TrackerSampleApp::PrepareScene() @@ -390,13 +392,13 @@ p[4] = 0; p[5] = 0; - scene_.SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); + GetScene()->SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); l->SetOrigin(-3, 2); l->SetPixelSpacing(1.5, 1); l->SetAngle(20.0 / 180.0 * M_PI); - scene_.SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); + GetScene()->SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); } // Texture of 1x1 size @@ -411,7 +413,7 @@ std::auto_ptr<ColorTextureSceneLayer> l(new ColorTextureSceneLayer(i)); l->SetOrigin(-2, 1); l->SetAngle(20.0 / 180.0 * M_PI); - scene_.SetLayer(TEXTURE_1x1_ZINDEX, l.release()); + GetScene()->SetLayer(TEXTURE_1x1_ZINDEX, l.release()); } // Some lines @@ -443,14 +445,14 @@ layer->AddChain(chain, false); layer->SetColor(0, 255, 255); - scene_.SetLayer(LINESET_1_ZINDEX, layer.release()); + GetScene()->SetLayer(LINESET_1_ZINDEX, layer.release()); } // Some text { std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer); layer->SetText("Hello"); - scene_.SetLayer(LINESET_2_ZINDEX, layer.release()); + GetScene()->SetLayer(LINESET_2_ZINDEX, layer.release()); } } @@ -460,7 +462,7 @@ if (activeTracker_) { activeTracker_->Cancel(); - activeTracker_ = NULL; + activeTracker_.reset(); } } @@ -468,7 +470,7 @@ unsigned int canvasWidth, unsigned int canvasHeight) { - CairoCompositor compositor(scene_, canvasWidth, canvasHeight); + CairoCompositor compositor(*GetScene(), canvasWidth, canvasHeight); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); compositor.Refresh(); @@ -486,7 +488,7 @@ FlexiblePointerTrackerPtr TrackerSampleApp::TrackerHitTest(const PointerEvent & e) { // std::vector<MeasureToolPtr> measureTools_; - return nullptr; + return FlexiblePointerTrackerPtr(); } static void GLAPIENTRY @@ -514,12 +516,12 @@ // that needs to be scaled SdlOpenGLWindow window("Hello", 1024, 1024, false); - GetScene().FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + controller_->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - compositor_.reset(new OpenGLCompositor(window, GetScene())); + compositor_.reset(new OpenGLCompositor(window, *GetScene())); compositor_->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); @@ -564,6 +566,9 @@ } SDL_Delay(1); } + + // the following is paramount because the compositor holds a reference + // to the scene and we do not want this reference to become dangling compositor_.reset(NULL); }
--- a/Samples/Sdl/TrackerSampleApp.h Thu May 16 19:10:38 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Tue May 21 13:25:58 2019 +0200 @@ -18,11 +18,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ -#include <Framework/Scene2D/OpenGLCompositor.h> +#include <Framework/Scene2DViewport/PointerTypes.h> + #include <Framework/Messages/IObserver.h> -#include "../Common/IFlexiblePointerTracker.h" -#include "../Common/MeasureTools.h" +#include <Framework/Scene2D/OpenGLCompositor.h> + +#include <Framework/Scene2DViewport/ViewportController.h> +#include <Framework/Scene2DViewport/IFlexiblePointerTracker.h> +#include <Framework/Scene2DViewport/MeasureTools.h> #include <SDL.h> @@ -32,9 +36,6 @@ namespace OrthancStone { - class TrackerCommand; - typedef boost::shared_ptr<TrackerCommand> TrackerCommandPtr; - enum GuiTool { GuiTool_Rotate = 0, @@ -65,7 +66,7 @@ void SetInfoDisplayMessage(std::string key, std::string value); void DisableTracker(); - Scene2D& GetScene(); + Scene2DPtr GetScene(); void HandleApplicationEvent(const SDL_Event& event); @@ -73,7 +74,8 @@ This method is called when the scene transform changes. It allows to recompute the visual elements whose content depend upon the scene transform */ - void OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message); + void OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message); private: void SelectNextTool(); @@ -108,18 +110,13 @@ WARNING: the measuring tools do store a reference to the scene, and it paramount that the scene gets destroyed AFTER the measurement tools. */ - Scene2D scene_; + ViewportControllerPtr controller_; std::map<std::string, std::string> infoTextMap_; FlexiblePointerTrackerPtr activeTracker_; - std::vector<TrackerCommandPtr> undoStack_; - - // we store the measure tools here so that they don't get deleted - std::vector<MeasureToolPtr> measureTools_; //static const int LAYER_POSITION = 150; - int TEXTURE_2x2_1_ZINDEX; int TEXTURE_1x1_ZINDEX; int TEXTURE_2x2_2_ZINDEX;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/TestStrategy.cpp Tue May 21 13:25:58 2019 +0200 @@ -0,0 +1,391 @@ +/** + * 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 "gtest/gtest.h" + +#include "../Framework/Loaders/BasicFetchingStrategy.h" +#include "../Framework/Loaders/BasicFetchingItemsSorter.h" + +#include <Core/OrthancException.h> + + +namespace +{ + class StrategyTester : public boost::noncopyable + { + private: + std::map<unsigned int, unsigned int> qualities_; + + public: + bool IsValidCommand(unsigned int item, + unsigned int quality) + { + if (qualities_.find(item) != qualities_.end() && + qualities_[item] >= quality) + { + return false; + } + else + { + qualities_[item] = quality; + return true; + } + } + + bool HasFinished(OrthancStone::BasicFetchingStrategy& strategy) + { + for (unsigned int i = 0; i < strategy.GetItemsCount(); i++) + { + if (qualities_.find(i) == qualities_.end() || + qualities_[i] != strategy.GetMaxQuality()) + { + return false; + } + } + + return true; + } + }; +} + + +TEST(BasicFetchingStrategy, Test1) +{ + ASSERT_THROW(OrthancStone::BasicFetchingStrategy(NULL, 0), Orthanc::OrthancException); + ASSERT_THROW(OrthancStone::BasicFetchingStrategy(new OrthancStone::BasicFetchingItemsSorter(0), 0), Orthanc::OrthancException); + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(1), 0); + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(0u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(1), 5); + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(5u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(2), 2); + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(2u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(1u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(2u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(3), 2); + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(2u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(1u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(1u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(2u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(2u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(3), 2); + s.SetBlockSize(1); + s.SetCurrent(0); + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(2u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(1u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(2u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(1u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(2u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(5), 0); + ASSERT_THROW(s.SetCurrent(5), Orthanc::OrthancException); + s.SetCurrent(2); + + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(3u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(4u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(0u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } + + { + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(5), 0); + s.SetCurrent(4); + + unsigned int i, q; + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(4u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(3u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(2u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(1u, i); ASSERT_EQ(0u, q); + ASSERT_TRUE(s.GetNext(i, q)); ASSERT_EQ(0u, i); ASSERT_EQ(0u, q); + ASSERT_FALSE(s.GetNext(i, q)); + } +} + + +TEST(BasicFetchingStrategy, Test2) +{ + OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(20), 2); + ASSERT_EQ(20u, s.GetItemsCount()); + ASSERT_EQ(2u, s.GetMaxQuality()); + + StrategyTester t; + + s.SetCurrent(10); + + unsigned int i, q; + while (s.GetNext(i, q)) + { + ASSERT_TRUE(t.IsValidCommand(i, q)); + } + + ASSERT_TRUE(t.HasFinished(s)); +} + + + + +TEST(BasicFetchingItemsSorter, Small) +{ + ASSERT_THROW(OrthancStone::BasicFetchingItemsSorter(0), Orthanc::OrthancException); + std::vector<unsigned int> v; + + { + OrthancStone::BasicFetchingItemsSorter s(1); + s.Sort(v, 0); + ASSERT_EQ(1u, v.size()); + ASSERT_EQ(0u, v[0]); + + ASSERT_THROW(s.Sort(v, 1), Orthanc::OrthancException); + } + + { + OrthancStone::BasicFetchingItemsSorter s(2); + s.Sort(v, 0); + ASSERT_EQ(2u, v.size()); + ASSERT_EQ(0u, v[0]); + ASSERT_EQ(1u, v[1]); + + s.Sort(v, 1); + ASSERT_EQ(2u, v.size()); + ASSERT_EQ(1u, v[0]); + ASSERT_EQ(0u, v[1]); + + ASSERT_THROW(s.Sort(v, 2), Orthanc::OrthancException); + } + + { + OrthancStone::BasicFetchingItemsSorter s(3); + s.Sort(v, 0); + ASSERT_EQ(3u, v.size()); + ASSERT_EQ(0u, v[0]); + ASSERT_EQ(1u, v[1]); + ASSERT_EQ(2u, v[2]); + + s.Sort(v, 1); + ASSERT_EQ(3u, v.size()); + ASSERT_EQ(1u, v[0]); + ASSERT_EQ(2u, v[1]); + ASSERT_EQ(0u, v[2]); + + s.Sort(v, 2); + ASSERT_EQ(3u, v.size()); + ASSERT_EQ(2u, v[0]); + ASSERT_EQ(1u, v[1]); + ASSERT_EQ(0u, v[2]); + + ASSERT_THROW(s.Sort(v, 3), Orthanc::OrthancException); + } +} + + +TEST(BasicFetchingItemsSorter, Odd) +{ + OrthancStone::BasicFetchingItemsSorter s(7); + std::vector<unsigned int> v; + + ASSERT_THROW(s.Sort(v, 7), Orthanc::OrthancException); + + { + s.Sort(v, 0); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(0u, v[0]); + ASSERT_EQ(1u, v[1]); + ASSERT_EQ(2u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(4u, v[4]); + ASSERT_EQ(5u, v[5]); + ASSERT_EQ(6u, v[6]); + } + + { + s.Sort(v, 1); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(1u, v[0]); + ASSERT_EQ(2u, v[1]); + ASSERT_EQ(0u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(4u, v[4]); + ASSERT_EQ(5u, v[5]); + ASSERT_EQ(6u, v[6]); + } + + { + s.Sort(v, 2); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(2u, v[0]); + ASSERT_EQ(3u, v[1]); + ASSERT_EQ(1u, v[2]); + ASSERT_EQ(4u, v[3]); + ASSERT_EQ(0u, v[4]); + ASSERT_EQ(5u, v[5]); + ASSERT_EQ(6u, v[6]); + } + + { + s.Sort(v, 3); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(3u, v[0]); + ASSERT_EQ(4u, v[1]); + ASSERT_EQ(2u, v[2]); + ASSERT_EQ(5u, v[3]); + ASSERT_EQ(1u, v[4]); + ASSERT_EQ(6u, v[5]); + ASSERT_EQ(0u, v[6]); + } + + { + s.Sort(v, 4); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(4u, v[0]); + ASSERT_EQ(5u, v[1]); + ASSERT_EQ(3u, v[2]); + ASSERT_EQ(6u, v[3]); + ASSERT_EQ(2u, v[4]); + ASSERT_EQ(1u, v[5]); + ASSERT_EQ(0u, v[6]); + } + + { + s.Sort(v, 5); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(5u, v[0]); + ASSERT_EQ(6u, v[1]); + ASSERT_EQ(4u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(2u, v[4]); + ASSERT_EQ(1u, v[5]); + ASSERT_EQ(0u, v[6]); + } + + { + s.Sort(v, 6); + ASSERT_EQ(7u, v.size()); + ASSERT_EQ(6u, v[0]); + ASSERT_EQ(5u, v[1]); + ASSERT_EQ(4u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(2u, v[4]); + ASSERT_EQ(1u, v[5]); + ASSERT_EQ(0u, v[6]); + } +} + + +TEST(BasicFetchingItemsSorter, Even) +{ + OrthancStone::BasicFetchingItemsSorter s(6); + std::vector<unsigned int> v; + + { + s.Sort(v, 0); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(0u, v[0]); + ASSERT_EQ(1u, v[1]); + ASSERT_EQ(2u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(4u, v[4]); + ASSERT_EQ(5u, v[5]); + } + + { + s.Sort(v, 1); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(1u, v[0]); + ASSERT_EQ(2u, v[1]); + ASSERT_EQ(0u, v[2]); + ASSERT_EQ(3u, v[3]); + ASSERT_EQ(4u, v[4]); + ASSERT_EQ(5u, v[5]); + } + + { + s.Sort(v, 2); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(2u, v[0]); + ASSERT_EQ(3u, v[1]); + ASSERT_EQ(1u, v[2]); + ASSERT_EQ(4u, v[3]); + ASSERT_EQ(0u, v[4]); + ASSERT_EQ(5u, v[5]); + } + + { + s.Sort(v, 3); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(3u, v[0]); + ASSERT_EQ(4u, v[1]); + ASSERT_EQ(2u, v[2]); + ASSERT_EQ(5u, v[3]); + ASSERT_EQ(1u, v[4]); + ASSERT_EQ(0u, v[5]); + } + + { + s.Sort(v, 4); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(4u, v[0]); + ASSERT_EQ(5u, v[1]); + ASSERT_EQ(3u, v[2]); + ASSERT_EQ(2u, v[3]); + ASSERT_EQ(1u, v[4]); + ASSERT_EQ(0u, v[5]); + } + + { + s.Sort(v, 5); + ASSERT_EQ(6u, v.size()); + ASSERT_EQ(5u, v[0]); + ASSERT_EQ(4u, v[1]); + ASSERT_EQ(3u, v[2]); + ASSERT_EQ(2u, v[3]); + ASSERT_EQ(1u, v[4]); + ASSERT_EQ(0u, v[5]); + } +}
--- a/UnitTestsSources/UnitTestsMain.cpp Thu May 16 19:10:38 2019 +0200 +++ b/UnitTestsSources/UnitTestsMain.cpp Tue May 21 13:25:58 2019 +0200 @@ -730,6 +730,82 @@ ASSERT_TRUE(OrthancStone::MessagingToolbox::ParseJson(response, source.c_str(), source.size())); } +TEST(VolumeImageGeometry, Basic) +{ + OrthancStone::VolumeImageGeometry g; + g.SetSize(10, 20, 30); + g.SetVoxelDimensions(1, 2, 3); + + OrthancStone::Vector p = g.GetCoordinates(0, 0, 0); + ASSERT_EQ(3u, p.size()); + ASSERT_FLOAT_EQ(-1.0 / 2.0, p[0]); + ASSERT_FLOAT_EQ(-2.0 / 2.0, p[1]); + ASSERT_FLOAT_EQ(-3.0 / 2.0, p[2]); + + p = g.GetCoordinates(1, 1, 1); + ASSERT_FLOAT_EQ(-1.0 / 2.0 + 10.0 * 1.0, p[0]); + ASSERT_FLOAT_EQ(-2.0 / 2.0 + 20.0 * 2.0, p[1]); + ASSERT_FLOAT_EQ(-3.0 / 2.0 + 30.0 * 3.0, p[2]); + + OrthancStone::VolumeProjection proj; + ASSERT_TRUE(g.DetectProjection(proj, g.GetAxialGeometry().GetNormal())); + ASSERT_EQ(OrthancStone::VolumeProjection_Axial, proj); + ASSERT_TRUE(g.DetectProjection(proj, g.GetCoronalGeometry().GetNormal())); + ASSERT_EQ(OrthancStone::VolumeProjection_Coronal, proj); + ASSERT_TRUE(g.DetectProjection(proj, g.GetSagittalGeometry().GetNormal())); + ASSERT_EQ(OrthancStone::VolumeProjection_Sagittal, proj); + + ASSERT_EQ(10u, g.GetProjectionWidth(OrthancStone::VolumeProjection_Axial)); + ASSERT_EQ(20u, g.GetProjectionHeight(OrthancStone::VolumeProjection_Axial)); + ASSERT_EQ(30u, g.GetProjectionDepth(OrthancStone::VolumeProjection_Axial)); + ASSERT_EQ(10u, g.GetProjectionWidth(OrthancStone::VolumeProjection_Coronal)); + ASSERT_EQ(30u, g.GetProjectionHeight(OrthancStone::VolumeProjection_Coronal)); + ASSERT_EQ(20u, g.GetProjectionDepth(OrthancStone::VolumeProjection_Coronal)); + ASSERT_EQ(20u, g.GetProjectionWidth(OrthancStone::VolumeProjection_Sagittal)); + ASSERT_EQ(30u, g.GetProjectionHeight(OrthancStone::VolumeProjection_Sagittal)); + ASSERT_EQ(10u, g.GetProjectionDepth(OrthancStone::VolumeProjection_Sagittal)); + + p = g.GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); + ASSERT_EQ(3u, p.size()); + ASSERT_FLOAT_EQ(1, p[0]); + ASSERT_FLOAT_EQ(2, p[1]); + ASSERT_FLOAT_EQ(3, p[2]); + p = g.GetVoxelDimensions(OrthancStone::VolumeProjection_Coronal); + ASSERT_EQ(3u, p.size()); + ASSERT_FLOAT_EQ(1, p[0]); + ASSERT_FLOAT_EQ(3, p[1]); + ASSERT_FLOAT_EQ(2, p[2]); + p = g.GetVoxelDimensions(OrthancStone::VolumeProjection_Sagittal); + ASSERT_EQ(3u, p.size()); + ASSERT_FLOAT_EQ(2, p[0]); + ASSERT_FLOAT_EQ(3, p[1]); + ASSERT_FLOAT_EQ(1, p[2]); + + ASSERT_EQ(0, (int) OrthancStone::VolumeProjection_Axial); + ASSERT_EQ(1, (int) OrthancStone::VolumeProjection_Coronal); + ASSERT_EQ(2, (int) OrthancStone::VolumeProjection_Sagittal); + + for (int p = 0; p < 3; p++) + { + OrthancStone::VolumeProjection projection = (OrthancStone::VolumeProjection) p; + const OrthancStone::CoordinateSystem3D& s = g.GetProjectionGeometry(projection); + + for (unsigned int i = 0; i < g.GetProjectionDepth(projection); i++) + { + OrthancStone::CoordinateSystem3D plane( + s.GetOrigin() + static_cast<double>(i) * s.GetNormal() * g.GetVoxelDimensions(projection)[2], + s.GetAxisX(), + s.GetAxisY()); + + unsigned int slice; + OrthancStone::VolumeProjection q; + ASSERT_TRUE(g.DetectSlice(q, slice, plane)); + ASSERT_EQ(projection, q); + ASSERT_EQ(i, slice); + } + } +} + int main(int argc, char **argv) { Orthanc::Logging::Initialize();