Mercurial > hg > orthanc-stone
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 } |