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