comparison Framework/Radiography/RadiographyScene.cpp @ 410:6decc0ba9da5

rename RadiographyScene::Layer as RadiographyLayer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 12 Nov 2018 15:52:03 +0100
parents 99c9b3238008
children 71c16998fcc8
comparison
equal deleted inserted replaced
409:99c9b3238008 410:6decc0ba9da5
19 **/ 19 **/
20 20
21 21
22 #include "RadiographyScene.h" 22 #include "RadiographyScene.h"
23 23
24 #include "../Toolbox/ImageGeometry.h"
25 #include "../Toolbox/DicomFrameConverter.h" 24 #include "../Toolbox/DicomFrameConverter.h"
26 25
27 #include <Core/Images/Image.h> 26 #include <Core/Images/Image.h>
28 #include <Core/Images/ImageProcessing.h> 27 #include <Core/Images/ImageProcessing.h>
29 #include <Core/Images/PamReader.h> 28 #include <Core/Images/PamReader.h>
35 #include <Plugins/Samples/Common/FullOrthancDataset.h> 34 #include <Plugins/Samples/Common/FullOrthancDataset.h>
36 35
37 36
38 namespace OrthancStone 37 namespace OrthancStone
39 { 38 {
40 static double Square(double x)
41 {
42 return x * x;
43 }
44
45
46 void RadiographyScene::Layer::UpdateTransform()
47 {
48 transform_ = AffineTransform2D::CreateScaling(pixelSpacingX_, pixelSpacingY_);
49
50 double centerX, centerY;
51 GetCenter(centerX, centerY);
52
53 transform_ = AffineTransform2D::Combine(
54 AffineTransform2D::CreateOffset(panX_ + centerX, panY_ + centerY),
55 AffineTransform2D::CreateRotation(angle_),
56 AffineTransform2D::CreateOffset(-centerX, -centerY),
57 transform_);
58
59 transformInverse_ = AffineTransform2D::Invert(transform_);
60 }
61
62
63 void RadiographyScene::Layer::AddToExtent(Extent2D& extent,
64 double x,
65 double y) const
66 {
67 transform_.Apply(x, y);
68 extent.AddPoint(x, y);
69 }
70
71
72 void RadiographyScene::Layer::GetCornerInternal(double& x,
73 double& y,
74 Corner corner,
75 unsigned int cropX,
76 unsigned int cropY,
77 unsigned int cropWidth,
78 unsigned int cropHeight) const
79 {
80 double dx = static_cast<double>(cropX);
81 double dy = static_cast<double>(cropY);
82 double dwidth = static_cast<double>(cropWidth);
83 double dheight = static_cast<double>(cropHeight);
84
85 switch (corner)
86 {
87 case Corner_TopLeft:
88 x = dx;
89 y = dy;
90 break;
91
92 case Corner_TopRight:
93 x = dx + dwidth;
94 y = dy;
95 break;
96
97 case Corner_BottomLeft:
98 x = dx;
99 y = dy + dheight;
100 break;
101
102 case Corner_BottomRight:
103 x = dx + dwidth;
104 y = dy + dheight;
105 break;
106
107 default:
108 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
109 }
110
111 transform_.Apply(x, y);
112 }
113
114
115 bool RadiographyScene::Layer::Contains(double x,
116 double y) const
117 {
118 transformInverse_.Apply(x, y);
119
120 unsigned int cropX, cropY, cropWidth, cropHeight;
121 GetCrop(cropX, cropY, cropWidth, cropHeight);
122
123 return (x >= cropX && x <= cropX + cropWidth &&
124 y >= cropY && y <= cropY + cropHeight);
125 }
126
127
128 void RadiographyScene::Layer::DrawBorders(CairoContext& context,
129 double zoom)
130 {
131 unsigned int cx, cy, width, height;
132 GetCrop(cx, cy, width, height);
133
134 double dx = static_cast<double>(cx);
135 double dy = static_cast<double>(cy);
136 double dwidth = static_cast<double>(width);
137 double dheight = static_cast<double>(height);
138
139 cairo_t* cr = context.GetObject();
140 cairo_set_line_width(cr, 2.0 / zoom);
141
142 double x, y;
143 x = dx;
144 y = dy;
145 transform_.Apply(x, y);
146 cairo_move_to(cr, x, y);
147
148 x = dx + dwidth;
149 y = dy;
150 transform_.Apply(x, y);
151 cairo_line_to(cr, x, y);
152
153 x = dx + dwidth;
154 y = dy + dheight;
155 transform_.Apply(x, y);
156 cairo_line_to(cr, x, y);
157
158 x = dx;
159 y = dy + dheight;
160 transform_.Apply(x, y);
161 cairo_line_to(cr, x, y);
162
163 x = dx;
164 y = dy;
165 transform_.Apply(x, y);
166 cairo_line_to(cr, x, y);
167
168 cairo_stroke(cr);
169 }
170
171
172 RadiographyScene::Layer::Layer() :
173 index_(0),
174 hasSize_(false),
175 width_(0),
176 height_(0),
177 hasCrop_(false),
178 pixelSpacingX_(1),
179 pixelSpacingY_(1),
180 panX_(0),
181 panY_(0),
182 angle_(0),
183 resizeable_(false)
184 {
185 UpdateTransform();
186 }
187
188
189 void RadiographyScene::Layer::SetCrop(unsigned int x,
190 unsigned int y,
191 unsigned int width,
192 unsigned int height)
193 {
194 if (!hasSize_)
195 {
196 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
197 }
198
199 if (x + width > width_ ||
200 y + height > height_)
201 {
202 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
203 }
204
205 hasCrop_ = true;
206 cropX_ = x;
207 cropY_ = y;
208 cropWidth_ = width;
209 cropHeight_ = height;
210
211 UpdateTransform();
212 }
213
214
215 void RadiographyScene::Layer::GetCrop(unsigned int& x,
216 unsigned int& y,
217 unsigned int& width,
218 unsigned int& height) const
219 {
220 if (hasCrop_)
221 {
222 x = cropX_;
223 y = cropY_;
224 width = cropWidth_;
225 height = cropHeight_;
226 }
227 else
228 {
229 x = 0;
230 y = 0;
231 width = width_;
232 height = height_;
233 }
234 }
235
236
237 void RadiographyScene::Layer::SetAngle(double angle)
238 {
239 angle_ = angle;
240 UpdateTransform();
241 }
242
243
244 void RadiographyScene::Layer::SetSize(unsigned int width,
245 unsigned int height)
246 {
247 if (hasSize_ &&
248 (width != width_ ||
249 height != height_))
250 {
251 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize);
252 }
253
254 hasSize_ = true;
255 width_ = width;
256 height_ = height;
257
258 UpdateTransform();
259 }
260
261
262 Extent2D RadiographyScene::Layer::GetExtent() const
263 {
264 Extent2D extent;
265
266 unsigned int x, y, width, height;
267 GetCrop(x, y, width, height);
268
269 double dx = static_cast<double>(x);
270 double dy = static_cast<double>(y);
271 double dwidth = static_cast<double>(width);
272 double dheight = static_cast<double>(height);
273
274 AddToExtent(extent, dx, dy);
275 AddToExtent(extent, dx + dwidth, dy);
276 AddToExtent(extent, dx, dy + dheight);
277 AddToExtent(extent, dx + dwidth, dy + dheight);
278
279 return extent;
280 }
281
282
283 bool RadiographyScene::Layer::GetPixel(unsigned int& imageX,
284 unsigned int& imageY,
285 double sceneX,
286 double sceneY) const
287 {
288 if (width_ == 0 ||
289 height_ == 0)
290 {
291 return false;
292 }
293 else
294 {
295 transformInverse_.Apply(sceneX, sceneY);
296
297 int x = static_cast<int>(std::floor(sceneX));
298 int y = static_cast<int>(std::floor(sceneY));
299
300 if (x < 0)
301 {
302 imageX = 0;
303 }
304 else if (x >= static_cast<int>(width_))
305 {
306 imageX = width_;
307 }
308 else
309 {
310 imageX = static_cast<unsigned int>(x);
311 }
312
313 if (y < 0)
314 {
315 imageY = 0;
316 }
317 else if (y >= static_cast<int>(height_))
318 {
319 imageY = height_;
320 }
321 else
322 {
323 imageY = static_cast<unsigned int>(y);
324 }
325
326 return true;
327 }
328 }
329
330
331 void RadiographyScene::Layer::SetPan(double x,
332 double y)
333 {
334 panX_ = x;
335 panY_ = y;
336 UpdateTransform();
337 }
338
339
340 void RadiographyScene::Layer::SetPixelSpacing(double x,
341 double y)
342 {
343 pixelSpacingX_ = x;
344 pixelSpacingY_ = y;
345 UpdateTransform();
346 }
347
348
349 void RadiographyScene::Layer::GetCenter(double& centerX,
350 double& centerY) const
351 {
352 centerX = static_cast<double>(width_) / 2.0;
353 centerY = static_cast<double>(height_) / 2.0;
354 transform_.Apply(centerX, centerY);
355 }
356
357
358 void RadiographyScene::Layer::GetCorner(double& x /* out */,
359 double& y /* out */,
360 Corner corner) const
361 {
362 unsigned int cropX, cropY, cropWidth, cropHeight;
363 GetCrop(cropX, cropY, cropWidth, cropHeight);
364 GetCornerInternal(x, y, corner, cropX, cropY, cropWidth, cropHeight);
365 }
366
367
368 bool RadiographyScene::Layer::LookupCorner(Corner& corner /* out */,
369 double x,
370 double y,
371 double zoom,
372 double viewportDistance) const
373 {
374 static const Corner CORNERS[] = {
375 Corner_TopLeft,
376 Corner_TopRight,
377 Corner_BottomLeft,
378 Corner_BottomRight
379 };
380
381 unsigned int cropX, cropY, cropWidth, cropHeight;
382 GetCrop(cropX, cropY, cropWidth, cropHeight);
383
384 double threshold = Square(viewportDistance / zoom);
385
386 for (size_t i = 0; i < 4; i++)
387 {
388 double cx, cy;
389 GetCornerInternal(cx, cy, CORNERS[i], cropX, cropY, cropWidth, cropHeight);
390
391 double d = Square(cx - x) + Square(cy - y);
392
393 if (d <= threshold)
394 {
395 corner = CORNERS[i];
396 return true;
397 }
398 }
399
400 return false;
401 }
402
403
404
405 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, 39 RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene,
406 size_t index) : 40 size_t index) :
407 scene_(scene), 41 scene_(scene),
408 index_(index) 42 index_(index)
409 { 43 {
471 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 105 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
472 } 106 }
473 } 107 }
474 108
475 109
476 RadiographyScene::Layer& RadiographyScene::LayerAccessor::GetLayer() const 110 RadiographyLayer& RadiographyScene::LayerAccessor::GetLayer() const
477 { 111 {
478 if (IsValid()) 112 if (IsValid())
479 { 113 {
480 return *layer_; 114 return *layer_;
481 } 115 }
485 } 119 }
486 } 120 }
487 121
488 122
489 123
490 class RadiographyScene::AlphaLayer : public Layer 124 class RadiographyScene::AlphaLayer : public RadiographyLayer
491 { 125 {
492 private: 126 private:
493 const RadiographyScene& scene_; 127 const RadiographyScene& scene_;
494 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8 128 std::auto_ptr<Orthanc::ImageAccessor> alpha_; // Grayscale8
495 bool useWindowing_; 129 bool useWindowing_;
629 } 263 }
630 }; 264 };
631 265
632 266
633 267
634 class RadiographyScene::DicomLayer : public Layer 268 class RadiographyScene::DicomLayer : public RadiographyLayer
635 { 269 {
636 private: 270 private:
637 std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData 271 std::auto_ptr<Orthanc::ImageAccessor> source_; // Content of PixelData
638 std::auto_ptr<DicomFrameConverter> converter_; 272 std::auto_ptr<DicomFrameConverter> converter_;
639 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32 273 std::auto_ptr<Orthanc::ImageAccessor> converted_; // Float32
765 } 399 }
766 } 400 }
767 }; 401 };
768 402
769 403
770 RadiographyScene::Layer& RadiographyScene::RegisterLayer(RadiographyScene::Layer* layer) 404 RadiographyLayer& RadiographyScene::RegisterLayer(RadiographyLayer* layer)
771 { 405 {
772 if (layer == NULL) 406 if (layer == NULL)
773 { 407 {
774 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 408 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
775 } 409 }
776 410
777 std::auto_ptr<Layer> raii(layer); 411 std::auto_ptr<RadiographyLayer> raii(layer);
778 412
779 size_t index = countLayers_++; 413 size_t index = countLayers_++;
780 raii->SetIndex(index); 414 raii->SetIndex(index);
781 layers_[index] = raii.release(); 415 layers_[index] = raii.release();
782 416
844 windowingCenter_ = center; 478 windowingCenter_ = center;
845 windowingWidth_ = width; 479 windowingWidth_ = width;
846 } 480 }
847 481
848 482
849 RadiographyScene::Layer& RadiographyScene::LoadText(const Orthanc::Font& font, 483 RadiographyLayer& RadiographyScene::LoadText(const Orthanc::Font& font,
850 const std::string& utf8) 484 const std::string& utf8)
851 { 485 {
852 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this)); 486 std::auto_ptr<AlphaLayer> alpha(new AlphaLayer(*this));
853 alpha->LoadText(font, utf8); 487 alpha->LoadText(font, utf8);
854 488
855 return RegisterLayer(alpha.release()); 489 return RegisterLayer(alpha.release());
856 } 490 }
857 491
858 492
859 RadiographyScene::Layer& RadiographyScene::LoadTestBlock(unsigned int width, 493 RadiographyLayer& RadiographyScene::LoadTestBlock(unsigned int width,
860 unsigned int height) 494 unsigned int height)
861 { 495 {
862 std::auto_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); 496 std::auto_ptr<Orthanc::Image> block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false));
863 497
864 for (unsigned int padding = 0; 498 for (unsigned int padding = 0;
865 (width > 2 * padding) && (height > 2 * padding); 499 (width > 2 * padding) && (height > 2 * padding);
885 519
886 return RegisterLayer(alpha.release()); 520 return RegisterLayer(alpha.release());
887 } 521 }
888 522
889 523
890 RadiographyScene::Layer& RadiographyScene::LoadDicomFrame(const std::string& instance, 524 RadiographyLayer& RadiographyScene::LoadDicomFrame(const std::string& instance,
891 unsigned int frame, 525 unsigned int frame,
892 bool httpCompression) 526 bool httpCompression)
893 { 527 {
894 Layer& layer = RegisterLayer(new DicomLayer); 528 RadiographyLayer& layer = RegisterLayer(new DicomLayer);
895 529
896 { 530 {
897 IWebService::Headers headers; 531 IWebService::Headers headers;
898 std::string uri = "/instances/" + instance + "/tags"; 532 std::string uri = "/instances/" + instance + "/tags";
899 533