Mercurial > hg > orthanc-stone
annotate Framework/dev.h @ 110:53025eecbc95 wasm
renamed SliceGeometry as CoordinateSystem3D
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 14 Jun 2017 15:50:38 +0200 |
parents | eccd64f8e297 |
children | 948f86e61e83 |
rev | line source |
---|---|
102 | 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 #pragma once | |
23 | |
24 #include "Layers/FrameRenderer.h" | |
25 #include "Layers/LayerSourceBase.h" | |
26 #include "Layers/SliceOutlineRenderer.h" | |
104
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
27 #include "Widgets/LayerWidget.h" |
102 | 28 #include "Toolbox/DownloadStack.h" |
29 #include "Toolbox/OrthancSlicesLoader.h" | |
30 #include "Volumes/ImageBuffer3D.h" | |
31 #include "Volumes/SlicedVolumeBase.h" | |
32 | |
33 #include "../Resources/Orthanc/Core/Logging.h" | |
34 #include "../Resources/Orthanc/Core/Images/ImageProcessing.h" | |
35 | |
36 #include <boost/math/special_functions/round.hpp> | |
37 | |
38 | |
39 namespace OrthancStone | |
40 { | |
41 class OrthancVolumeImage : | |
42 public SlicedVolumeBase, | |
43 private OrthancSlicesLoader::ICallback | |
44 { | |
45 private: | |
46 OrthancSlicesLoader loader_; | |
47 std::auto_ptr<ImageBuffer3D> image_; | |
48 std::auto_ptr<DownloadStack> downloadStack_; | |
49 | |
50 | |
51 void ScheduleSliceDownload() | |
52 { | |
53 assert(downloadStack_.get() != NULL); | |
54 | |
55 unsigned int slice; | |
56 if (downloadStack_->Pop(slice)) | |
57 { | |
58 loader_.ScheduleLoadSliceImage(slice, SliceImageQuality_Jpeg90); | |
59 } | |
60 } | |
61 | |
62 | |
63 static bool IsCompatible(const Slice& a, | |
64 const Slice& b) | |
65 { | |
66 if (!GeometryToolbox::IsParallel(a.GetGeometry().GetNormal(), | |
67 b.GetGeometry().GetNormal())) | |
68 { | |
69 LOG(ERROR) << "Some slice in the volume image is not parallel to the others"; | |
70 return false; | |
71 } | |
72 | |
73 if (a.GetConverter().GetExpectedPixelFormat() != b.GetConverter().GetExpectedPixelFormat()) | |
74 { | |
75 LOG(ERROR) << "The pixel format changes across the slices of the volume image"; | |
76 return false; | |
77 } | |
78 | |
79 if (a.GetWidth() != b.GetWidth() || | |
80 a.GetHeight() != b.GetHeight()) | |
81 { | |
82 LOG(ERROR) << "The width/height of the slices change across the volume image"; | |
83 return false; | |
84 } | |
85 | |
86 if (!GeometryToolbox::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || | |
87 !GeometryToolbox::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) | |
88 { | |
89 LOG(ERROR) << "The pixel spacing of the slices change across the volume image"; | |
90 return false; | |
91 } | |
92 | |
93 return true; | |
94 } | |
95 | |
96 | |
97 static double GetDistance(const Slice& a, | |
98 const Slice& b) | |
99 { | |
100 return fabs(a.GetGeometry().ProjectAlongNormal(a.GetGeometry().GetOrigin()) - | |
101 a.GetGeometry().ProjectAlongNormal(b.GetGeometry().GetOrigin())); | |
102 } | |
103 | |
104 | |
105 virtual void NotifyGeometryReady(const OrthancSlicesLoader& loader) | |
106 { | |
107 if (loader.GetSliceCount() == 0) | |
108 { | |
109 LOG(ERROR) << "Empty volume image"; | |
110 SlicedVolumeBase::NotifyGeometryError(); | |
111 return; | |
112 } | |
113 | |
114 for (size_t i = 1; i < loader.GetSliceCount(); i++) | |
115 { | |
116 if (!IsCompatible(loader.GetSlice(0), loader.GetSlice(i))) | |
117 { | |
118 SlicedVolumeBase::NotifyGeometryError(); | |
119 return; | |
120 } | |
121 } | |
122 | |
123 double spacingZ; | |
124 | |
125 if (loader.GetSliceCount() > 1) | |
126 { | |
127 spacingZ = GetDistance(loader.GetSlice(0), loader.GetSlice(1)); | |
128 } | |
129 else | |
130 { | |
131 // This is a volume with one single slice: Choose a dummy | |
132 // z-dimension for voxels | |
133 spacingZ = 1; | |
134 } | |
135 | |
136 for (size_t i = 1; i < loader.GetSliceCount(); i++) | |
137 { | |
138 if (!GeometryToolbox::IsNear(spacingZ, GetDistance(loader.GetSlice(i - 1), loader.GetSlice(i)), | |
139 0.001 /* this is expressed in mm */)) | |
140 { | |
141 LOG(ERROR) << "The distance between successive slices is not constant in a volume image"; | |
142 SlicedVolumeBase::NotifyGeometryError(); | |
143 return; | |
144 } | |
145 } | |
146 | |
147 unsigned int width = loader.GetSlice(0).GetWidth(); | |
148 unsigned int height = loader.GetSlice(0).GetHeight(); | |
149 Orthanc::PixelFormat format = loader.GetSlice(0).GetConverter().GetExpectedPixelFormat(); | |
150 LOG(INFO) << "Creating a volume image of size " << width << "x" << height | |
151 << "x" << loader.GetSliceCount() << " in " << Orthanc::EnumerationToString(format); | |
152 | |
153 image_.reset(new ImageBuffer3D(format, width, height, loader.GetSliceCount())); | |
154 image_->SetAxialGeometry(loader.GetSlice(0).GetGeometry()); | |
155 image_->SetVoxelDimensions(loader.GetSlice(0).GetPixelSpacingX(), | |
156 loader.GetSlice(0).GetPixelSpacingY(), spacingZ); | |
157 image_->Clear(); | |
158 | |
159 downloadStack_.reset(new DownloadStack(loader.GetSliceCount())); | |
160 | |
161 for (unsigned int i = 0; i < 4; i++) // Limit to 4 simultaneous downloads | |
162 { | |
163 ScheduleSliceDownload(); | |
164 } | |
165 | |
166 // TODO Check the DicomFrameConverter are constant | |
167 | |
168 SlicedVolumeBase::NotifyGeometryReady(); | |
169 } | |
170 | |
171 virtual void NotifyGeometryError(const OrthancSlicesLoader& loader) | |
172 { | |
173 LOG(ERROR) << "Unable to download a volume image"; | |
174 SlicedVolumeBase::NotifyGeometryError(); | |
175 } | |
176 | |
177 virtual void NotifySliceImageReady(const OrthancSlicesLoader& loader, | |
178 unsigned int sliceIndex, | |
179 const Slice& slice, | |
180 std::auto_ptr<Orthanc::ImageAccessor>& image, | |
181 SliceImageQuality quality) | |
182 { | |
183 { | |
184 ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, sliceIndex); | |
185 Orthanc::ImageProcessing::Copy(writer.GetAccessor(), *image); | |
186 } | |
187 | |
188 SlicedVolumeBase::NotifySliceChange(sliceIndex, slice); | |
189 | |
190 ScheduleSliceDownload(); | |
191 } | |
192 | |
193 virtual void NotifySliceImageError(const OrthancSlicesLoader& loader, | |
194 unsigned int sliceIndex, | |
195 const Slice& slice, | |
196 SliceImageQuality quality) | |
197 { | |
198 LOG(ERROR) << "Cannot download slice " << sliceIndex << " in a volume image"; | |
199 ScheduleSliceDownload(); | |
200 } | |
201 | |
202 public: | |
203 OrthancVolumeImage(IWebService& orthanc) : | |
204 loader_(*this, orthanc) | |
205 { | |
206 } | |
207 | |
208 void ScheduleLoadSeries(const std::string& seriesId) | |
209 { | |
210 loader_.ScheduleLoadSeries(seriesId); | |
211 } | |
212 | |
213 void ScheduleLoadInstance(const std::string& instanceId, | |
214 unsigned int frame) | |
215 { | |
216 loader_.ScheduleLoadInstance(instanceId, frame); | |
217 } | |
218 | |
219 virtual size_t GetSliceCount() const | |
220 { | |
221 return loader_.GetSliceCount(); | |
222 } | |
223 | |
224 virtual const Slice& GetSlice(size_t index) const | |
225 { | |
226 return loader_.GetSlice(index); | |
227 } | |
228 | |
229 ImageBuffer3D& GetImage() const | |
230 { | |
231 if (image_.get() == NULL) | |
232 { | |
233 // The geometry is not ready yet | |
234 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
235 } | |
236 else | |
237 { | |
238 return *image_; | |
239 } | |
240 } | |
241 }; | |
242 | |
243 | |
244 class VolumeImageGeometry | |
245 { | |
246 private: | |
247 unsigned int width_; | |
248 unsigned int height_; | |
249 size_t depth_; | |
250 double pixelSpacingX_; | |
251 double pixelSpacingY_; | |
252 double sliceThickness_; | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
253 CoordinateSystem3D reference_; |
102 | 254 DicomFrameConverter converter_; |
255 | |
256 double ComputeAxialThickness(const OrthancVolumeImage& volume) const | |
257 { | |
258 double thickness; | |
259 | |
260 size_t n = volume.GetSliceCount(); | |
261 if (n > 1) | |
262 { | |
263 const Slice& a = volume.GetSlice(0); | |
264 const Slice& b = volume.GetSlice(n - 1); | |
265 thickness = ((reference_.ProjectAlongNormal(b.GetGeometry().GetOrigin()) - | |
266 reference_.ProjectAlongNormal(a.GetGeometry().GetOrigin())) / | |
267 (static_cast<double>(n) - 1.0)); | |
268 } | |
269 else | |
270 { | |
271 thickness = volume.GetSlice(0).GetThickness(); | |
272 } | |
273 | |
274 if (thickness <= 0) | |
275 { | |
276 // The slices should have been sorted with increasing Z | |
277 // (along the normal) by the OrthancSlicesLoader | |
278 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
279 } | |
280 else | |
281 { | |
282 return thickness; | |
283 } | |
284 } | |
285 | |
286 void SetupAxial(const OrthancVolumeImage& volume) | |
287 { | |
288 const Slice& axial = volume.GetSlice(0); | |
289 | |
290 width_ = axial.GetWidth(); | |
291 height_ = axial.GetHeight(); | |
292 depth_ = volume.GetSliceCount(); | |
293 | |
294 pixelSpacingX_ = axial.GetPixelSpacingX(); | |
295 pixelSpacingY_ = axial.GetPixelSpacingY(); | |
296 sliceThickness_ = ComputeAxialThickness(volume); | |
297 | |
298 reference_ = axial.GetGeometry(); | |
299 } | |
300 | |
301 void SetupCoronal(const OrthancVolumeImage& volume) | |
302 { | |
303 const Slice& axial = volume.GetSlice(0); | |
304 double axialThickness = ComputeAxialThickness(volume); | |
305 | |
306 width_ = axial.GetWidth(); | |
307 height_ = volume.GetSliceCount(); | |
308 depth_ = axial.GetHeight(); | |
309 | |
310 pixelSpacingX_ = axial.GetPixelSpacingX(); | |
311 pixelSpacingY_ = axialThickness; | |
312 sliceThickness_ = axial.GetPixelSpacingY(); | |
313 | |
314 Vector origin = axial.GetGeometry().GetOrigin(); | |
315 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | |
316 axialThickness * axial.GetGeometry().GetNormal()); | |
317 | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
318 reference_ = CoordinateSystem3D(origin, |
102 | 319 axial.GetGeometry().GetAxisX(), |
320 -axial.GetGeometry().GetNormal()); | |
321 } | |
322 | |
323 void SetupSagittal(const OrthancVolumeImage& volume) | |
324 { | |
325 const Slice& axial = volume.GetSlice(0); | |
326 double axialThickness = ComputeAxialThickness(volume); | |
327 | |
328 width_ = axial.GetHeight(); | |
329 height_ = volume.GetSliceCount(); | |
330 depth_ = axial.GetWidth(); | |
331 | |
332 pixelSpacingX_ = axial.GetPixelSpacingY(); | |
333 pixelSpacingY_ = axialThickness; | |
334 sliceThickness_ = axial.GetPixelSpacingX(); | |
335 | |
336 Vector origin = axial.GetGeometry().GetOrigin(); | |
337 origin += (static_cast<double>(volume.GetSliceCount() - 1) * | |
338 axialThickness * axial.GetGeometry().GetNormal()); | |
339 | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
340 reference_ = CoordinateSystem3D(origin, |
102 | 341 axial.GetGeometry().GetAxisY(), |
342 axial.GetGeometry().GetNormal()); | |
343 } | |
344 | |
345 public: | |
346 VolumeImageGeometry(const OrthancVolumeImage& volume, | |
347 VolumeProjection projection) | |
348 { | |
349 if (volume.GetSliceCount() == 0) | |
350 { | |
351 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
352 } | |
353 | |
354 converter_ = volume.GetSlice(0).GetConverter(); | |
355 | |
356 switch (projection) | |
357 { | |
358 case VolumeProjection_Axial: | |
359 SetupAxial(volume); | |
360 break; | |
361 | |
362 case VolumeProjection_Coronal: | |
363 SetupCoronal(volume); | |
364 break; | |
365 | |
366 case VolumeProjection_Sagittal: | |
367 SetupSagittal(volume); | |
368 break; | |
369 | |
370 default: | |
371 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
372 } | |
373 } | |
374 | |
375 size_t GetSliceCount() const | |
376 { | |
377 return depth_; | |
378 } | |
379 | |
380 const Vector& GetNormal() const | |
381 { | |
382 return reference_.GetNormal(); | |
383 } | |
384 | |
385 bool LookupSlice(size_t& index, | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
386 const CoordinateSystem3D& slice) const |
102 | 387 { |
388 bool opposite; | |
389 if (!GeometryToolbox::IsParallelOrOpposite(opposite, | |
390 reference_.GetNormal(), | |
391 slice.GetNormal())) | |
392 { | |
393 return false; | |
394 } | |
395 | |
396 double z = (reference_.ProjectAlongNormal(slice.GetOrigin()) - | |
397 reference_.ProjectAlongNormal(reference_.GetOrigin())) / sliceThickness_; | |
398 | |
399 int s = static_cast<int>(boost::math::iround(z)); | |
400 | |
401 if (s < 0 || | |
402 s >= static_cast<int>(depth_)) | |
403 { | |
404 return false; | |
405 } | |
406 else | |
407 { | |
408 index = static_cast<size_t>(s); | |
409 return true; | |
410 } | |
411 } | |
412 | |
413 Slice GetSlice(size_t slice) const | |
414 { | |
415 if (slice < 0 || | |
416 slice >= depth_) | |
417 { | |
418 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
419 } | |
420 else | |
421 { | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
422 CoordinateSystem3D origin(reference_.GetOrigin() + |
102 | 423 static_cast<double>(slice) * sliceThickness_ * reference_.GetNormal(), |
424 reference_.GetAxisX(), | |
425 reference_.GetAxisY()); | |
426 | |
427 return Slice(origin, pixelSpacingX_, pixelSpacingY_, sliceThickness_, | |
428 width_, height_, converter_); | |
429 } | |
430 } | |
431 }; | |
432 | |
433 | |
434 | |
435 class VolumeImageSource : | |
436 public LayerSourceBase, | |
437 private ISlicedVolume::IObserver | |
438 { | |
439 private: | |
440 OrthancVolumeImage& volume_; | |
441 std::auto_ptr<VolumeImageGeometry> axialGeometry_; | |
442 std::auto_ptr<VolumeImageGeometry> coronalGeometry_; | |
443 std::auto_ptr<VolumeImageGeometry> sagittalGeometry_; | |
444 | |
445 | |
446 bool IsGeometryReady() const | |
447 { | |
448 return axialGeometry_.get() != NULL; | |
449 } | |
450 | |
451 | |
452 virtual void NotifyGeometryReady(const ISlicedVolume& volume) | |
453 { | |
454 // These 3 values are only used to speed up the ILayerSource | |
455 axialGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Axial)); | |
456 coronalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Coronal)); | |
457 sagittalGeometry_.reset(new VolumeImageGeometry(volume_, VolumeProjection_Sagittal)); | |
458 | |
459 LayerSourceBase::NotifyGeometryReady(); | |
460 } | |
461 | |
462 virtual void NotifyGeometryError(const ISlicedVolume& volume) | |
463 { | |
464 LayerSourceBase::NotifyGeometryError(); | |
465 } | |
466 | |
467 virtual void NotifyContentChange(const ISlicedVolume& volume) | |
468 { | |
469 LayerSourceBase::NotifyContentChange(); | |
470 } | |
471 | |
472 virtual void NotifySliceChange(const ISlicedVolume& volume, | |
473 const size_t& sliceIndex, | |
474 const Slice& slice) | |
475 { | |
476 //LayerSourceBase::NotifySliceChange(slice); | |
477 | |
478 // TODO Improve this? | |
479 LayerSourceBase::NotifyContentChange(); | |
480 } | |
481 | |
482 | |
483 const VolumeImageGeometry& GetProjectionGeometry(VolumeProjection projection) | |
484 { | |
485 if (!IsGeometryReady()) | |
486 { | |
487 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
488 } | |
489 | |
490 switch (projection) | |
491 { | |
492 case VolumeProjection_Axial: | |
493 return *axialGeometry_; | |
494 | |
495 case VolumeProjection_Sagittal: | |
496 return *sagittalGeometry_; | |
497 | |
498 case VolumeProjection_Coronal: | |
499 return *coronalGeometry_; | |
500 | |
501 default: | |
502 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
503 } | |
504 } | |
505 | |
506 | |
507 bool DetectProjection(VolumeProjection& projection, | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
508 const CoordinateSystem3D& viewportSlice) |
102 | 509 { |
510 bool isOpposite; // Ignored | |
511 | |
512 if (GeometryToolbox::IsParallelOrOpposite(isOpposite, | |
513 viewportSlice.GetNormal(), | |
514 axialGeometry_->GetNormal())) | |
515 { | |
516 projection = VolumeProjection_Axial; | |
517 return true; | |
518 } | |
519 else if (GeometryToolbox::IsParallelOrOpposite(isOpposite, | |
520 viewportSlice.GetNormal(), | |
521 sagittalGeometry_->GetNormal())) | |
522 { | |
523 projection = VolumeProjection_Sagittal; | |
524 return true; | |
525 } | |
526 else if (GeometryToolbox::IsParallelOrOpposite(isOpposite, | |
527 viewportSlice.GetNormal(), | |
528 coronalGeometry_->GetNormal())) | |
529 { | |
530 projection = VolumeProjection_Coronal; | |
531 return true; | |
532 } | |
533 else | |
534 { | |
535 return false; | |
536 } | |
537 } | |
538 | |
539 | |
540 public: | |
541 VolumeImageSource(OrthancVolumeImage& volume) : | |
542 volume_(volume) | |
543 { | |
544 volume_.Register(*this); | |
545 } | |
546 | |
547 virtual bool GetExtent(std::vector<Vector>& points, | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
548 const CoordinateSystem3D& viewportSlice) |
102 | 549 { |
550 VolumeProjection projection; | |
551 | |
552 if (!IsGeometryReady() || | |
553 !DetectProjection(projection, viewportSlice)) | |
554 { | |
555 return false; | |
556 } | |
557 else | |
558 { | |
559 // As the slices of the volumic image are arranged in a box, | |
560 // we only consider one single reference slice (the one with index 0). | |
561 GetProjectionGeometry(projection).GetSlice(0).GetExtent(points); | |
562 | |
563 return true; | |
564 } | |
565 } | |
566 | |
567 | |
110
53025eecbc95
renamed SliceGeometry as CoordinateSystem3D
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
104
diff
changeset
|
568 virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) |
102 | 569 { |
570 VolumeProjection projection; | |
571 | |
572 if (IsGeometryReady() && | |
573 DetectProjection(projection, viewportSlice)) | |
574 { | |
575 const VolumeImageGeometry& geometry = GetProjectionGeometry(projection); | |
576 | |
577 size_t closest; | |
578 | |
579 if (geometry.LookupSlice(closest, viewportSlice)) | |
580 { | |
581 bool isFullQuality = true; // TODO | |
582 | |
583 std::auto_ptr<Orthanc::Image> frame; | |
584 | |
585 { | |
586 ImageBuffer3D::SliceReader reader(volume_.GetImage(), projection, closest); | |
587 | |
588 // TODO Transfer ownership if non-axial, to avoid memcpy | |
589 frame.reset(Orthanc::Image::Clone(reader.GetAccessor())); | |
590 } | |
591 | |
592 Slice slice = geometry.GetSlice(closest); | |
593 LayerSourceBase::NotifyLayerReady( | |
594 FrameRenderer::CreateRenderer(frame.release(), slice, isFullQuality), | |
595 //new SliceOutlineRenderer(slice), | |
596 slice, false); | |
597 return; | |
598 } | |
599 } | |
600 | |
601 // Error | |
602 Slice slice; | |
603 LayerSourceBase::NotifyLayerReady(NULL, slice, true); | |
604 } | |
605 }; | |
104
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
606 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
607 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
608 class VolumeImageInteractor : |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
609 public IWorldSceneInteractor, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
610 private ISlicedVolume::IObserver |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
611 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
612 private: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
613 LayerWidget& widget_; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
614 VolumeProjection projection_; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
615 std::auto_ptr<VolumeImageGeometry> slices_; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
616 size_t slice_; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
617 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
618 virtual void NotifyGeometryReady(const ISlicedVolume& volume) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
619 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
620 if (slices_.get() == NULL) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
621 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
622 const OrthancVolumeImage& image = dynamic_cast<const OrthancVolumeImage&>(volume); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
623 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
624 slices_.reset(new VolumeImageGeometry(image, projection_)); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
625 SetSlice(slices_->GetSliceCount() / 2); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
626 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
627 widget_.SetDefaultView(); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
628 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
629 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
630 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
631 virtual void NotifyGeometryError(const ISlicedVolume& volume) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
632 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
633 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
634 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
635 virtual void NotifyContentChange(const ISlicedVolume& volume) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
636 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
637 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
638 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
639 virtual void NotifySliceChange(const ISlicedVolume& volume, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
640 const size_t& sliceIndex, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
641 const Slice& slice) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
642 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
643 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
644 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
645 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
646 const ViewportGeometry& view, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
647 MouseButton button, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
648 double x, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
649 double y, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
650 IStatusBar* statusBar) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
651 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
652 return NULL; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
653 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
654 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
655 virtual void MouseOver(CairoContext& context, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
656 WorldSceneWidget& widget, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
657 const ViewportGeometry& view, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
658 double x, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
659 double y, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
660 IStatusBar* statusBar) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
661 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
662 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
663 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
664 virtual void MouseWheel(WorldSceneWidget& widget, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
665 MouseWheelDirection direction, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
666 KeyboardModifiers modifiers, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
667 IStatusBar* statusBar) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
668 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
669 int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
670 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
671 switch (direction) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
672 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
673 case MouseWheelDirection_Up: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
674 OffsetSlice(-scale); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
675 break; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
676 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
677 case MouseWheelDirection_Down: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
678 OffsetSlice(scale); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
679 break; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
680 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
681 default: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
682 break; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
683 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
684 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
685 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
686 virtual void KeyPressed(WorldSceneWidget& widget, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
687 char key, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
688 KeyboardModifiers modifiers, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
689 IStatusBar* statusBar) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
690 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
691 switch (key) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
692 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
693 case 's': |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
694 widget.SetDefaultView(); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
695 break; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
696 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
697 default: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
698 break; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
699 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
700 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
701 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
702 public: |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
703 VolumeImageInteractor(OrthancVolumeImage& volume, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
704 LayerWidget& widget, |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
705 VolumeProjection projection) : |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
706 widget_(widget), |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
707 projection_(projection) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
708 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
709 volume.Register(*this); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
710 widget.SetInteractor(*this); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
711 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
712 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
713 bool IsGeometryReady() const |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
714 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
715 return slices_.get() != NULL; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
716 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
717 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
718 size_t GetSliceCount() const |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
719 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
720 if (slices_.get() == NULL) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
721 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
722 return 0; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
723 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
724 else |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
725 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
726 return slices_->GetSliceCount(); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
727 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
728 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
729 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
730 void OffsetSlice(int offset) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
731 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
732 if (slices_.get() != NULL) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
733 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
734 int slice = static_cast<int>(slice_) + offset; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
735 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
736 if (slice < 0) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
737 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
738 slice = 0; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
739 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
740 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
741 if (slice >= static_cast<int>(slices_->GetSliceCount())) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
742 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
743 slice = slices_->GetSliceCount() - 1; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
744 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
745 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
746 if (slice != static_cast<int>(slice_)) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
747 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
748 SetSlice(slice); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
749 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
750 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
751 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
752 |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
753 void SetSlice(size_t slice) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
754 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
755 if (slices_.get() != NULL) |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
756 { |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
757 slice_ = slice; |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
758 widget_.SetSlice(slices_->GetSlice(slice_).GetGeometry()); |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
759 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
760 } |
eccd64f8e297
VolumeImageInteractor
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
102
diff
changeset
|
761 }; |
102 | 762 } |