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