Mercurial > hg > orthanc-stone
diff Applications/Samples/SingleVolumeApplication.h @ 102:fcec0ab44054 wasm
display volumes
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 31 May 2017 17:01:18 +0200 |
parents | b340879da9bd |
children | 474d85e76499 |
line wrap: on
line diff
--- a/Applications/Samples/SingleVolumeApplication.h Wed May 31 10:35:20 2017 +0200 +++ b/Applications/Samples/SingleVolumeApplication.h Wed May 31 17:01:18 2017 +0200 @@ -21,7 +21,10 @@ #pragma once -#include "SampleInteractor.h" +#include "SampleApplicationBase.h" +#include "../../Framework/dev.h" +//#include "SampleInteractor.h" +#include "../../Framework/Widgets/LayerWidget.h" #include "../../Resources/Orthanc/Core/Toolbox.h" #include "../../Framework/Layers/LineMeasureTracker.h" @@ -32,9 +35,160 @@ { namespace Samples { - class SingleVolumeApplication : public SampleApplicationBase + class SingleVolumeApplication : + public SampleApplicationBase, + private ILayerSource::IObserver { private: + class Interactor : public IWorldSceneInteractor + { + private: + SingleVolumeApplication& application_; + + public: + Interactor(SingleVolumeApplication& application) : + application_(application) + { + } + + virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, + const ViewportGeometry& view, + MouseButton button, + double x, + double y, + IStatusBar* statusBar) + { + return NULL; + } + + virtual void MouseOver(CairoContext& context, + WorldSceneWidget& widget, + const ViewportGeometry& view, + double x, + double y, + IStatusBar* statusBar) + { + if (statusBar != NULL) + { + Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); + + char buf[64]; + sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", + p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); + statusBar->SetMessage(buf); + } + } + + virtual void MouseWheel(WorldSceneWidget& widget, + MouseWheelDirection direction, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + { + int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); + + switch (direction) + { + case MouseWheelDirection_Up: + application_.OffsetSlice(-scale); + break; + + case MouseWheelDirection_Down: + application_.OffsetSlice(scale); + break; + + default: + break; + } + } + + virtual void KeyPressed(WorldSceneWidget& widget, + char key, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + { + switch (key) + { + case 's': + widget.SetDefaultView(); + break; + + default: + break; + } + } + }; + + + LayerWidget* widget_; + OrthancVolumeImage* volume_; + VolumeProjection projection_; + std::auto_ptr<VolumeImageGeometry> slices_; + size_t slice_; + + void OffsetSlice(int offset) + { + if (slices_.get() != NULL) + { + int slice = static_cast<int>(slice_) + offset; + + if (slice < 0) + { + slice = 0; + } + + if (slice >= static_cast<int>(slices_->GetSliceCount())) + { + slice = slices_->GetSliceCount() - 1; + } + + if (slice != static_cast<int>(slice_)) + { + SetSlice(slice); + } + } + } + + void SetSlice(size_t slice) + { + if (slices_.get() != NULL) + { + slice_ = slice; + widget_->SetSlice(slices_->GetSlice(slice_).GetGeometry()); + } + } + + virtual void NotifyGeometryReady(const ILayerSource& source) + { + if (slices_.get() == NULL) + { + slices_.reset(new VolumeImageGeometry(*volume_, projection_)); + SetSlice(slices_->GetSliceCount() / 2); + + widget_->SetDefaultView(); + } + } + + virtual void NotifyGeometryError(const ILayerSource& source) + { + } + + virtual void NotifyContentChange(const ILayerSource& source) + { + } + + virtual void NotifySliceChange(const ILayerSource& source, + const Slice& slice) + { + } + + virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer, + const ILayerSource& source, + const Slice& slice, + bool isError) + { + } + +#if 0 class Interactor : public SampleInteractor { private: @@ -204,9 +358,16 @@ } } }; - +#endif + public: + SingleVolumeApplication() : + widget_(NULL), + volume_(NULL) + { + } + virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) { boost::program_options::options_description generic("Sample options"); @@ -243,18 +404,17 @@ std::string tmp = parameters["projection"].as<std::string>(); Orthanc::Toolbox::ToLowerCase(tmp); - VolumeProjection projection; if (tmp == "axial") { - projection = VolumeProjection_Axial; + projection_ = VolumeProjection_Axial; } else if (tmp == "sagittal") { - projection = VolumeProjection_Sagittal; + projection_ = VolumeProjection_Sagittal; } else if (tmp == "coronal") { - projection = VolumeProjection_Coronal; + projection_ = VolumeProjection_Coronal; } else { @@ -262,22 +422,74 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } - VolumeImage& volume = context.AddSeriesVolume(series, true /* progressive download */, threads); + std::auto_ptr<LayerWidget> widget(new LayerWidget); + widget_ = widget.get(); + +#if 0 + std::auto_ptr<OrthancVolumeImage> volume(new OrthancVolumeImage(context.GetWebService())); + volume->ScheduleLoadSeries(series); - std::auto_ptr<Interactor> interactor(new Interactor(volume, projection, reverse)); + volume_ = volume.get(); + + { + std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*volume)); + source->Register(*this); + widget->AddLayer(source.release()); + } + + context.AddVolume(volume.release()); +#else + std::auto_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context.GetWebService())); + ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d"); + + std::auto_ptr<OrthancVolumeImage> pet(new OrthancVolumeImage(context.GetWebService())); + pet->ScheduleLoadSeries("aabad2e7-80702b5d-e599d26c-4f13398e-38d58a9e"); - std::auto_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); - widget->AddLayer(new VolumeImage::LayerFactory(volume)); - widget->SetSlice(interactor->GetCursor().GetCurrentSlice()); - widget->SetInteractor(*interactor); + volume_ = pet.get(); + + { + std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*ct)); + //source->Register(*this); + widget->AddLayer(source.release()); + } + + { + std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*pet)); + source->Register(*this); + widget->AddLayer(source.release()); + } + + context.AddVolume(ct.release()); + context.AddVolume(pet.release()); - context.AddInteractor(interactor.release()); - context.SetCentralWidget(widget.release()); + { + RenderStyle s; + //s.drawGrid_ = true; + s.alpha_ = 1; + widget->SetLayerStyle(0, s); + } + + { + RenderStyle s; + //s.drawGrid_ = true; + s.SetColor(255, 0, 0); // Draw missing PET layer in red + s.alpha_ = 0.5; + s.applyLut_ = true; + s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET; + s.interpolation_ = ImageInterpolation_Linear; + widget->SetLayerStyle(1, s); + } +#endif + statusBar.SetMessage("Use the keys \"b\", \"l\" and \"d\" to change Hounsfield windowing"); statusBar.SetMessage("Use the keys \"t\" to track the (X,Y,Z) mouse coordinates"); statusBar.SetMessage("Use the keys \"m\" to measure distances"); statusBar.SetMessage("Use the keys \"c\" to draw circles"); + + widget->SetTransmitMouseOver(true); + widget->SetInteractor(context.AddInteractor(new Interactor(*this))); + context.SetCentralWidget(widget.release()); } }; }