Mercurial > hg > orthanc-stone
comparison Applications/Samples/SimpleViewerApplication.h @ 235:ce4405d98b92 am
Added SimpleViewerApplication (working in SDL)
author | am@osimis.io |
---|---|
date | Tue, 19 Jun 2018 16:02:41 +0200 |
parents | |
children | b4642964c355 |
comparison
equal
deleted
inserted
replaced
234:9afb50d1ac14 | 235:ce4405d98b92 |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #pragma once | |
23 | |
24 #include "SampleApplicationBase.h" | |
25 | |
26 #include "../../Framework/Layers/OrthancFrameLayerSource.h" | |
27 #include "../../Framework/Widgets/LayerWidget.h" | |
28 #include "../../Framework/Widgets/LayoutWidget.h" | |
29 | |
30 #include <Core/Logging.h> | |
31 | |
32 namespace OrthancStone | |
33 { | |
34 namespace Samples | |
35 { | |
36 class SimpleViewerApplication : | |
37 public SampleApplicationBase, | |
38 private ILayerSource::IObserver | |
39 { | |
40 private: | |
41 class Interactor : public IWorldSceneInteractor | |
42 { | |
43 private: | |
44 SimpleViewerApplication& application_; | |
45 | |
46 public: | |
47 Interactor(SimpleViewerApplication& application) : | |
48 application_(application) | |
49 { | |
50 } | |
51 | |
52 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, | |
53 const ViewportGeometry& view, | |
54 MouseButton button, | |
55 double x, | |
56 double y, | |
57 IStatusBar* statusBar) | |
58 { | |
59 return NULL; | |
60 } | |
61 | |
62 virtual void MouseOver(CairoContext& context, | |
63 WorldSceneWidget& widget, | |
64 const ViewportGeometry& view, | |
65 double x, | |
66 double y, | |
67 IStatusBar* statusBar) | |
68 { | |
69 if (statusBar != NULL) | |
70 { | |
71 Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); | |
72 | |
73 char buf[64]; | |
74 sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", | |
75 p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); | |
76 statusBar->SetMessage(buf); | |
77 } | |
78 } | |
79 | |
80 virtual void MouseWheel(WorldSceneWidget& widget, | |
81 MouseWheelDirection direction, | |
82 KeyboardModifiers modifiers, | |
83 IStatusBar* statusBar) | |
84 { | |
85 // int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); | |
86 | |
87 // switch (direction) | |
88 // { | |
89 // case MouseWheelDirection_Up: | |
90 // application_.OffsetSlice(-scale); | |
91 // break; | |
92 | |
93 // case MouseWheelDirection_Down: | |
94 // application_.OffsetSlice(scale); | |
95 // break; | |
96 | |
97 // default: | |
98 // break; | |
99 // } | |
100 } | |
101 | |
102 virtual void KeyPressed(WorldSceneWidget& widget, | |
103 char key, | |
104 KeyboardModifiers modifiers, | |
105 IStatusBar* statusBar) | |
106 { | |
107 switch (key) | |
108 { | |
109 case 's': | |
110 widget.SetDefaultView(); | |
111 break; | |
112 | |
113 default: | |
114 break; | |
115 } | |
116 } | |
117 }; | |
118 | |
119 | |
120 // void OffsetSlice(int offset) | |
121 // { | |
122 // if (source_ != NULL) | |
123 // { | |
124 // int slice = static_cast<int>(slice_) + offset; | |
125 | |
126 // if (slice < 0) | |
127 // { | |
128 // slice = 0; | |
129 // } | |
130 | |
131 // if (slice >= static_cast<int>(source_->GetSliceCount())) | |
132 // { | |
133 // slice = source_->GetSliceCount() - 1; | |
134 // } | |
135 | |
136 // if (slice != static_cast<int>(slice_)) | |
137 // { | |
138 // SetSlice(slice); | |
139 // } | |
140 // } | |
141 // } | |
142 | |
143 | |
144 // void SetSlice(size_t index) | |
145 // { | |
146 // if (source_ != NULL && | |
147 // index < source_->GetSliceCount()) | |
148 // { | |
149 // slice_ = index; | |
150 | |
151 //#if 1 | |
152 // widget_->SetSlice(source_->GetSlice(slice_).GetGeometry()); | |
153 //#else | |
154 // // TEST for scene extents - Rotate the axes | |
155 // double a = 15.0 / 180.0 * M_PI; | |
156 | |
157 //#if 1 | |
158 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
159 // Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0); | |
160 //#else | |
161 // // Flip the normal | |
162 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
163 // Vector y; GeometryToolbox::AssignVector(y, sin(a), -cos(a), 0); | |
164 //#endif | |
165 | |
166 // SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y); | |
167 // widget_->SetSlice(s); | |
168 //#endif | |
169 // } | |
170 // } | |
171 | |
172 | |
173 virtual void NotifyGeometryReady(const ILayerSource& source) | |
174 { | |
175 // Once the geometry of the series is downloaded from Orthanc, | |
176 // display its first slice, and adapt the viewport to fit this | |
177 // slice | |
178 if (source_ == &source) | |
179 { | |
180 //SetSlice(source_->GetSliceCount() / 2); | |
181 } | |
182 | |
183 mainLayout_->SetDefaultView(); | |
184 } | |
185 | |
186 virtual void NotifyGeometryError(const ILayerSource& source) | |
187 { | |
188 } | |
189 | |
190 virtual void NotifyContentChange(const ILayerSource& source) | |
191 { | |
192 } | |
193 | |
194 virtual void NotifySliceChange(const ILayerSource& source, | |
195 const Slice& slice) | |
196 { | |
197 } | |
198 | |
199 virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer, | |
200 const ILayerSource& source, | |
201 const CoordinateSystem3D& slice, | |
202 bool isError) | |
203 { | |
204 } | |
205 | |
206 LayoutWidget* mainLayout_; | |
207 LayoutWidget* thumbnailsLayout_; | |
208 LayerWidget* mainViewport_; | |
209 std::vector<LayerWidget*> thumbnails_; | |
210 std::vector<std::string> instances_; | |
211 unsigned int currentInstanceIndex_; | |
212 | |
213 OrthancFrameLayerSource* source_; | |
214 unsigned int slice_; | |
215 | |
216 public: | |
217 SimpleViewerApplication() : | |
218 mainLayout_(NULL), | |
219 currentInstanceIndex_(0), | |
220 source_(NULL), | |
221 slice_(0) | |
222 { | |
223 } | |
224 | |
225 virtual void DeclareStartupOptions(boost::program_options::options_description& options) | |
226 { | |
227 boost::program_options::options_description generic("Sample options"); | |
228 generic.add_options() | |
229 // ("study", boost::program_options::value<std::string>(), | |
230 // "Orthanc ID of the study") | |
231 ("instance1", boost::program_options::value<std::string>(), | |
232 "Orthanc ID of the instances") | |
233 ("instance2", boost::program_options::value<std::string>(), | |
234 "Orthanc ID of the instances") | |
235 ; | |
236 | |
237 options.add(generic); | |
238 } | |
239 | |
240 virtual void Initialize(IStatusBar& statusBar, | |
241 const boost::program_options::variables_map& parameters) | |
242 { | |
243 using namespace OrthancStone; | |
244 | |
245 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); | |
246 | |
247 if (parameters.count("instance1") < 1) | |
248 { | |
249 LOG(ERROR) << "The instance ID is missing"; | |
250 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
251 } | |
252 if (parameters.count("instance2") < 1) | |
253 { | |
254 LOG(ERROR) << "The instance ID is missing"; | |
255 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
256 } | |
257 instances_.push_back(parameters["instance1"].as<std::string>()); | |
258 instances_.push_back(parameters["instance2"].as<std::string>()); | |
259 | |
260 mainLayout_ = new LayoutWidget(); | |
261 mainLayout_->SetPadding(10); | |
262 mainLayout_->SetBackgroundCleared(true); | |
263 mainLayout_->SetBackgroundColor(0, 0, 0); | |
264 mainLayout_->SetHorizontal(); | |
265 | |
266 thumbnailsLayout_ = new LayoutWidget(); | |
267 thumbnailsLayout_->SetPadding(10); | |
268 thumbnailsLayout_->SetBackgroundCleared(true); | |
269 thumbnailsLayout_->SetBackgroundColor(50, 50, 50); | |
270 thumbnailsLayout_->SetVertical(); | |
271 | |
272 mainViewport_ = new LayerWidget(); | |
273 thumbnails_.push_back(new LayerWidget()); | |
274 thumbnails_.push_back(new LayerWidget()); | |
275 | |
276 // hierarchy | |
277 mainLayout_->AddWidget(thumbnailsLayout_); | |
278 mainLayout_->AddWidget(mainViewport_); | |
279 thumbnailsLayout_->AddWidget(thumbnails_[0]); | |
280 thumbnailsLayout_->AddWidget(thumbnails_[1]); | |
281 | |
282 // sources | |
283 source_ = new OrthancFrameLayerSource(context_->GetWebService()); | |
284 source_->LoadFrame(instances_[currentInstanceIndex_], 0); | |
285 | |
286 mainViewport_->AddLayer(source_); | |
287 | |
288 OrthancFrameLayerSource* thumb0 = new OrthancFrameLayerSource(context_->GetWebService()); | |
289 thumb0->LoadFrame(instances_[0], 0); | |
290 OrthancFrameLayerSource* thumb1 = new OrthancFrameLayerSource(context_->GetWebService()); | |
291 thumb1->LoadFrame(instances_[1], 0); | |
292 | |
293 thumbnails_[0]->AddLayer(thumb0); | |
294 thumbnails_[1]->AddLayer(thumb1); | |
295 | |
296 mainLayout_->SetTransmitMouseOver(true); | |
297 mainViewport_->SetInteractor(context_->AddInteractor(new Interactor(*this))); | |
298 context_->SetCentralWidget(mainLayout_); | |
299 } | |
300 }; | |
301 } | |
302 } |