comparison 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
comparison
equal deleted inserted replaced
101:af312ce4fe59 102:fcec0ab44054
19 **/ 19 **/
20 20
21 21
22 #pragma once 22 #pragma once
23 23
24 #include "SampleInteractor.h" 24 #include "SampleApplicationBase.h"
25 #include "../../Framework/dev.h"
26 //#include "SampleInteractor.h"
27 #include "../../Framework/Widgets/LayerWidget.h"
25 28
26 #include "../../Resources/Orthanc/Core/Toolbox.h" 29 #include "../../Resources/Orthanc/Core/Toolbox.h"
27 #include "../../Framework/Layers/LineMeasureTracker.h" 30 #include "../../Framework/Layers/LineMeasureTracker.h"
28 #include "../../Framework/Layers/CircleMeasureTracker.h" 31 #include "../../Framework/Layers/CircleMeasureTracker.h"
29 #include "../../Resources/Orthanc/Core/Logging.h" 32 #include "../../Resources/Orthanc/Core/Logging.h"
30 33
31 namespace OrthancStone 34 namespace OrthancStone
32 { 35 {
33 namespace Samples 36 namespace Samples
34 { 37 {
35 class SingleVolumeApplication : public SampleApplicationBase 38 class SingleVolumeApplication :
39 public SampleApplicationBase,
40 private ILayerSource::IObserver
36 { 41 {
37 private: 42 private:
43 class Interactor : public IWorldSceneInteractor
44 {
45 private:
46 SingleVolumeApplication& application_;
47
48 public:
49 Interactor(SingleVolumeApplication& application) :
50 application_(application)
51 {
52 }
53
54 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
55 const ViewportGeometry& view,
56 MouseButton button,
57 double x,
58 double y,
59 IStatusBar* statusBar)
60 {
61 return NULL;
62 }
63
64 virtual void MouseOver(CairoContext& context,
65 WorldSceneWidget& widget,
66 const ViewportGeometry& view,
67 double x,
68 double y,
69 IStatusBar* statusBar)
70 {
71 if (statusBar != NULL)
72 {
73 Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y);
74
75 char buf[64];
76 sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)",
77 p[0] / 10.0, p[1] / 10.0, p[2] / 10.0);
78 statusBar->SetMessage(buf);
79 }
80 }
81
82 virtual void MouseWheel(WorldSceneWidget& widget,
83 MouseWheelDirection direction,
84 KeyboardModifiers modifiers,
85 IStatusBar* statusBar)
86 {
87 int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1);
88
89 switch (direction)
90 {
91 case MouseWheelDirection_Up:
92 application_.OffsetSlice(-scale);
93 break;
94
95 case MouseWheelDirection_Down:
96 application_.OffsetSlice(scale);
97 break;
98
99 default:
100 break;
101 }
102 }
103
104 virtual void KeyPressed(WorldSceneWidget& widget,
105 char key,
106 KeyboardModifiers modifiers,
107 IStatusBar* statusBar)
108 {
109 switch (key)
110 {
111 case 's':
112 widget.SetDefaultView();
113 break;
114
115 default:
116 break;
117 }
118 }
119 };
120
121
122 LayerWidget* widget_;
123 OrthancVolumeImage* volume_;
124 VolumeProjection projection_;
125 std::auto_ptr<VolumeImageGeometry> slices_;
126 size_t slice_;
127
128 void OffsetSlice(int offset)
129 {
130 if (slices_.get() != NULL)
131 {
132 int slice = static_cast<int>(slice_) + offset;
133
134 if (slice < 0)
135 {
136 slice = 0;
137 }
138
139 if (slice >= static_cast<int>(slices_->GetSliceCount()))
140 {
141 slice = slices_->GetSliceCount() - 1;
142 }
143
144 if (slice != static_cast<int>(slice_))
145 {
146 SetSlice(slice);
147 }
148 }
149 }
150
151 void SetSlice(size_t slice)
152 {
153 if (slices_.get() != NULL)
154 {
155 slice_ = slice;
156 widget_->SetSlice(slices_->GetSlice(slice_).GetGeometry());
157 }
158 }
159
160 virtual void NotifyGeometryReady(const ILayerSource& source)
161 {
162 if (slices_.get() == NULL)
163 {
164 slices_.reset(new VolumeImageGeometry(*volume_, projection_));
165 SetSlice(slices_->GetSliceCount() / 2);
166
167 widget_->SetDefaultView();
168 }
169 }
170
171 virtual void NotifyGeometryError(const ILayerSource& source)
172 {
173 }
174
175 virtual void NotifyContentChange(const ILayerSource& source)
176 {
177 }
178
179 virtual void NotifySliceChange(const ILayerSource& source,
180 const Slice& slice)
181 {
182 }
183
184 virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer,
185 const ILayerSource& source,
186 const Slice& slice,
187 bool isError)
188 {
189 }
190
191 #if 0
38 class Interactor : public SampleInteractor 192 class Interactor : public SampleInteractor
39 { 193 {
40 private: 194 private:
41 enum MouseMode 195 enum MouseMode
42 { 196 {
202 default: 356 default:
203 break; 357 break;
204 } 358 }
205 } 359 }
206 }; 360 };
207 361 #endif
208 362
363
209 public: 364 public:
365 SingleVolumeApplication() :
366 widget_(NULL),
367 volume_(NULL)
368 {
369 }
370
210 virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) 371 virtual void DeclareCommandLineOptions(boost::program_options::options_description& options)
211 { 372 {
212 boost::program_options::options_description generic("Sample options"); 373 boost::program_options::options_description generic("Sample options");
213 generic.add_options() 374 generic.add_options()
214 ("series", boost::program_options::value<std::string>(), 375 ("series", boost::program_options::value<std::string>(),
241 bool reverse = parameters["reverse"].as<bool>(); 402 bool reverse = parameters["reverse"].as<bool>();
242 403
243 std::string tmp = parameters["projection"].as<std::string>(); 404 std::string tmp = parameters["projection"].as<std::string>();
244 Orthanc::Toolbox::ToLowerCase(tmp); 405 Orthanc::Toolbox::ToLowerCase(tmp);
245 406
246 VolumeProjection projection;
247 if (tmp == "axial") 407 if (tmp == "axial")
248 { 408 {
249 projection = VolumeProjection_Axial; 409 projection_ = VolumeProjection_Axial;
250 } 410 }
251 else if (tmp == "sagittal") 411 else if (tmp == "sagittal")
252 { 412 {
253 projection = VolumeProjection_Sagittal; 413 projection_ = VolumeProjection_Sagittal;
254 } 414 }
255 else if (tmp == "coronal") 415 else if (tmp == "coronal")
256 { 416 {
257 projection = VolumeProjection_Coronal; 417 projection_ = VolumeProjection_Coronal;
258 } 418 }
259 else 419 else
260 { 420 {
261 LOG(ERROR) << "Unknown projection: " << tmp; 421 LOG(ERROR) << "Unknown projection: " << tmp;
262 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 422 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
263 } 423 }
264 424
265 VolumeImage& volume = context.AddSeriesVolume(series, true /* progressive download */, threads); 425 std::auto_ptr<LayerWidget> widget(new LayerWidget);
266 426 widget_ = widget.get();
267 std::auto_ptr<Interactor> interactor(new Interactor(volume, projection, reverse)); 427
268 428 #if 0
269 std::auto_ptr<LayeredSceneWidget> widget(new LayeredSceneWidget); 429 std::auto_ptr<OrthancVolumeImage> volume(new OrthancVolumeImage(context.GetWebService()));
270 widget->AddLayer(new VolumeImage::LayerFactory(volume)); 430 volume->ScheduleLoadSeries(series);
271 widget->SetSlice(interactor->GetCursor().GetCurrentSlice()); 431
272 widget->SetInteractor(*interactor); 432 volume_ = volume.get();
273 433
274 context.AddInteractor(interactor.release()); 434 {
275 context.SetCentralWidget(widget.release()); 435 std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*volume));
436 source->Register(*this);
437 widget->AddLayer(source.release());
438 }
439
440 context.AddVolume(volume.release());
441 #else
442 std::auto_ptr<OrthancVolumeImage> ct(new OrthancVolumeImage(context.GetWebService()));
443 ct->ScheduleLoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d");
444
445 std::auto_ptr<OrthancVolumeImage> pet(new OrthancVolumeImage(context.GetWebService()));
446 pet->ScheduleLoadSeries("aabad2e7-80702b5d-e599d26c-4f13398e-38d58a9e");
447
448 volume_ = pet.get();
449
450 {
451 std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*ct));
452 //source->Register(*this);
453 widget->AddLayer(source.release());
454 }
455
456 {
457 std::auto_ptr<VolumeImageSource> source(new VolumeImageSource(*pet));
458 source->Register(*this);
459 widget->AddLayer(source.release());
460 }
461
462 context.AddVolume(ct.release());
463 context.AddVolume(pet.release());
464
465 {
466 RenderStyle s;
467 //s.drawGrid_ = true;
468 s.alpha_ = 1;
469 widget->SetLayerStyle(0, s);
470 }
471
472 {
473 RenderStyle s;
474 //s.drawGrid_ = true;
475 s.SetColor(255, 0, 0); // Draw missing PET layer in red
476 s.alpha_ = 0.5;
477 s.applyLut_ = true;
478 s.lut_ = Orthanc::EmbeddedResources::COLORMAP_JET;
479 s.interpolation_ = ImageInterpolation_Linear;
480 widget->SetLayerStyle(1, s);
481 }
482 #endif
483
276 484
277 statusBar.SetMessage("Use the keys \"b\", \"l\" and \"d\" to change Hounsfield windowing"); 485 statusBar.SetMessage("Use the keys \"b\", \"l\" and \"d\" to change Hounsfield windowing");
278 statusBar.SetMessage("Use the keys \"t\" to track the (X,Y,Z) mouse coordinates"); 486 statusBar.SetMessage("Use the keys \"t\" to track the (X,Y,Z) mouse coordinates");
279 statusBar.SetMessage("Use the keys \"m\" to measure distances"); 487 statusBar.SetMessage("Use the keys \"m\" to measure distances");
280 statusBar.SetMessage("Use the keys \"c\" to draw circles"); 488 statusBar.SetMessage("Use the keys \"c\" to draw circles");
489
490 widget->SetTransmitMouseOver(true);
491 widget->SetInteractor(context.AddInteractor(new Interactor(*this)));
492 context.SetCentralWidget(widget.release());
281 } 493 }
282 }; 494 };
283 } 495 }
284 } 496 }