comparison Framework/Widgets/LayerWidget.cpp @ 66:298f375dcb68 wasm

LayerWidget
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 17 May 2017 22:03:09 +0200
parents
children 30c768873d47
comparison
equal deleted inserted replaced
65:885932a893de 66:298f375dcb68
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 Osimis, 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 #include "LayerWidget.h"
23
24 #include "../../Resources/Orthanc/Core/Logging.h"
25
26 namespace OrthancStone
27 {
28 class LayerWidget::Scene : public boost::noncopyable
29 {
30 private:
31 SliceGeometry slice_;
32 size_t countMissing_;
33 std::vector<ILayerRenderer*> renderers_;
34
35 void DeleteLayer(size_t index)
36 {
37 if (index >= renderers_.size())
38 {
39 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
40 }
41
42 assert(countMissing_ <= renderers_.size());
43
44 if (renderers_[index] != NULL)
45 {
46 assert(countMissing_ < renderers_.size());
47 delete renderers_[index];
48 renderers_[index] = NULL;
49 countMissing_++;
50 }
51 }
52
53 public:
54 Scene(const SliceGeometry& slice,
55 size_t countLayers) :
56 slice_(slice),
57 countMissing_(countLayers),
58 renderers_(countLayers, NULL)
59 {
60 }
61
62 ~Scene()
63 {
64 for (size_t i = 0; i < renderers_.size(); i++)
65 {
66 DeleteLayer(i);
67 }
68 }
69
70 void SetLayer(size_t index,
71 ILayerRenderer* renderer) // Takes ownership
72 {
73 if (renderer == NULL)
74 {
75 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
76 }
77
78 DeleteLayer(index);
79
80 renderers_[index] = renderer;
81 countMissing_--;
82 }
83
84 const SliceGeometry& GetSlice() const
85 {
86 return slice_;
87 }
88
89 bool IsComplete() const
90 {
91 return countMissing_ == 0;
92 }
93
94 bool IsSamePlane(const SliceGeometry& slice,
95 double sliceThickness)
96 {
97 return slice_.IsSamePlane(slice, sliceThickness);
98 }
99
100 bool RenderScene(CairoContext& context,
101 const ViewportGeometry& view)
102 {
103 bool fullQuality = true;
104
105 for (size_t i = 0; i < renderers_.size(); i++)
106 {
107 if (renderers_[i] != NULL &&
108 !renderers_[i]->RenderLayer(context, view))
109 {
110 return false;
111 }
112
113 if (renderers_[i] != NULL &&
114 !renderers_[i]->IsFullQuality())
115 {
116 fullQuality = false;
117 }
118 }
119
120 if (!fullQuality)
121 {
122 double x, y;
123 view.MapDisplayToScene(x, y, static_cast<double>(view.GetDisplayWidth()) / 2.0, 10);
124
125 cairo_t *cr = context.GetObject();
126 cairo_translate(cr, x, y);
127 cairo_arc(cr, 0, 0, 5.0 / view.GetZoom(), 0, 2 * M_PI);
128 cairo_set_line_width(cr, 2.0 / view.GetZoom());
129 cairo_set_source_rgb(cr, 1, 1, 1);
130 cairo_stroke_preserve(cr);
131 cairo_set_source_rgb(cr, 1, 0, 0);
132 cairo_fill(cr);
133 }
134
135 return true;
136 }
137
138 void SetLayerStyle(size_t index,
139 const RenderStyle& style)
140 {
141 if (renderers_[index] != NULL)
142 {
143 renderers_[index]->SetLayerStyle(style);
144 }
145 }
146 };
147
148
149 bool LayerWidget::LookupLayer(size_t& index /* out */,
150 ILayerSource& layer) const
151 {
152 LayersIndex::const_iterator found = layersIndex_.find(&layer);
153
154 if (found == layersIndex_.end())
155 {
156 return false;
157 }
158 else
159 {
160 index = found->second;
161 assert(index < layers_.size() &&
162 layers_[index] == &layer);
163 return true;
164 }
165 }
166
167
168 void LayerWidget::GetSceneExtent(double& x1,
169 double& y1,
170 double& x2,
171 double& y2)
172 {
173 bool first = true;
174
175 for (size_t i = 0; i < layers_.size(); i++)
176 {
177 double ax, ay, bx, by;
178
179 assert(layers_[i] != NULL);
180 if (layers_[i]->GetExtent(ax, ay, bx, by, slice_))
181 {
182 if (ax > bx)
183 {
184 std::swap(ax, bx);
185 }
186
187 if (ay > by)
188 {
189 std::swap(ay, by);
190 }
191
192 //LOG(INFO) << "Extent of layer " << i << ": (" << ax << "," << ay << ")->(" << bx << "," << by << ")";
193 printf("Extent %d: (%f,%f) -> (%f,%f)\n", (int) i, ax, ay, bx, by);
194
195 if (first)
196 {
197 x1 = ax;
198 y1 = ay;
199 x2 = bx;
200 y2 = by;
201 first = false;
202 }
203 else
204 {
205 x1 = std::min(x1, ax);
206 y1 = std::min(y1, ay);
207 x2 = std::max(x2, bx);
208 y2 = std::max(y2, by);
209 }
210 }
211 }
212
213 if (first)
214 {
215 // Set a default extent of (-1,-1) -> (0,0)
216 x1 = -1;
217 y1 = -1;
218 x2 = 1;
219 y2 = 1;
220 }
221
222 // Ensure the extent is non-empty
223 if (x1 >= x2)
224 {
225 double tmp = x1;
226 x1 = tmp - 0.5;
227 x2 = tmp + 0.5;
228 }
229
230 if (y1 >= y2)
231 {
232 double tmp = y1;
233 y1 = tmp - 0.5;
234 y2 = tmp + 0.5;
235 }
236 }
237
238
239 bool LayerWidget::RenderScene(CairoContext& context,
240 const ViewportGeometry& view)
241 {
242 if (currentScene_.get() != NULL)
243 {
244 return currentScene_->RenderScene(context, view);
245 }
246 else
247 {
248 return true;
249 }
250 }
251
252
253 void LayerWidget::ResetPendingScene()
254 {
255 pendingScene_.reset(new Scene(slice_, layers_.size()));
256 }
257
258
259 void LayerWidget::UpdateLayer(size_t index,
260 ILayerRenderer* renderer,
261 const SliceGeometry& slice)
262 {
263 printf("Updating layer %d\n", (int) index);
264
265 std::auto_ptr<ILayerRenderer> tmp(renderer);
266
267 if (renderer == NULL)
268 {
269 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
270 }
271
272 if (index >= layers_.size())
273 {
274 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
275 }
276
277 assert(layers_.size() == styles_.size());
278 renderer->SetLayerStyle(styles_[index]);
279
280 if (currentScene_.get() != NULL &&
281 currentScene_->IsSamePlane(slice, sliceThickness_))
282 {
283 currentScene_->SetLayer(index, tmp.release());
284 NotifyChange();
285 }
286 else if (pendingScene_.get() != NULL &&
287 pendingScene_->IsSamePlane(slice, sliceThickness_))
288 {
289 pendingScene_->SetLayer(index, tmp.release());
290
291 if (currentScene_.get() == NULL ||
292 pendingScene_->IsComplete())
293 {
294 currentScene_ = pendingScene_;
295 NotifyChange();
296 }
297 }
298 }
299
300
301 LayerWidget::LayerWidget() :
302 started_(false),
303 sliceThickness_(1)
304 {
305 SetBackgroundCleared(true);
306 }
307
308
309 LayerWidget::~LayerWidget()
310 {
311 for (size_t i = 0; i < layers_.size(); i++)
312 {
313 delete layers_[i];
314 }
315 }
316
317
318 size_t LayerWidget::AddLayer(ILayerSource* layer) // Takes ownership
319 {
320 if (layer == NULL)
321 {
322 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
323 }
324
325 size_t index = layers_.size();
326 layers_.push_back(layer);
327 styles_.push_back(RenderStyle());
328 layersIndex_[layer] = index;
329
330 ResetPendingScene();
331 layer->SetObserver(*this);
332
333 return index;
334 }
335
336
337 void LayerWidget::SetLayerStyle(size_t layer,
338 const RenderStyle& style)
339 {
340 if (layer >= layers_.size())
341 {
342 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
343 }
344
345 assert(layers_.size() == styles_.size());
346 styles_[layer] = style;
347
348 if (currentScene_.get() != NULL)
349 {
350 currentScene_->SetLayerStyle(layer, style);
351 }
352
353 if (pendingScene_.get() != NULL)
354 {
355 pendingScene_->SetLayerStyle(layer, style);
356 }
357
358 NotifyChange();
359 }
360
361
362 void LayerWidget::SetSlice(const SliceGeometry& slice,
363 double sliceThickness)
364 {
365 if (!slice_.IsSamePlane(slice, 100.0 * std::numeric_limits<double>::epsilon()))
366 {
367 if (currentScene_.get() == NULL ||
368 (pendingScene_.get() != NULL &&
369 pendingScene_->IsComplete()))
370 {
371 currentScene_ = pendingScene_;
372 }
373
374 slice_ = slice;
375 sliceThickness_ = sliceThickness;
376 ResetPendingScene();
377
378 if (started_)
379 {
380 for (size_t i = 0; i < layers_.size(); i++)
381 {
382 assert(layers_[i] != NULL);
383 layers_[i]->ScheduleLayerCreation(slice_);
384 }
385 }
386 }
387 }
388
389
390 void LayerWidget::NotifyGeometryReady(ILayerSource& source)
391 {
392 size_t i;
393 if (LookupLayer(i, source))
394 printf("Geometry ready for layer %d\n", (int) i);
395
396 SetDefaultView();
397 layers_[i]->ScheduleLayerCreation(slice_);
398 }
399
400
401 void LayerWidget::NotifySourceChange(ILayerSource& source)
402 {
403 source.ScheduleLayerCreation(slice_);
404 }
405
406
407 void LayerWidget::NotifySliceChange(ILayerSource& source,
408 const SliceGeometry& slice)
409 {
410 if (slice_.IsSamePlane(slice, sliceThickness_))
411 {
412 source.ScheduleLayerCreation(slice_);
413 }
414 }
415
416
417 void LayerWidget::NotifyLayerReady(ILayerRenderer* renderer,
418 ILayerSource& source,
419 const SliceGeometry& viewportSlice)
420 {
421 std::auto_ptr<ILayerRenderer> tmp(renderer);
422
423 size_t i;
424 if (LookupLayer(i, source))
425 printf("Renderer ready for layer %d\n", (int) i);
426
427 size_t index;
428 if (LookupLayer(index, source))
429 {
430 UpdateLayer(index, tmp.release(), viewportSlice);
431 }
432 }
433
434
435 void LayerWidget::NotifyLayerError(ILayerSource& source,
436 const SliceGeometry& viewportSlice)
437 {
438 size_t i;
439 if (LookupLayer(i, source))
440 LOG(ERROR) << "Error on layer " << i;
441 }
442
443
444 void LayerWidget::Start()
445 {
446 if (started_)
447 {
448 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
449 }
450
451 for (size_t i = 0; i < layers_.size(); i++)
452 {
453 assert(layers_[i] != NULL);
454 layers_[i]->Start();
455 }
456 }
457 }