comparison Framework/Deprecated/Radiography/RadiographyLayer.cpp @ 1398:c5403d52078c

moved Radiography into Deprecated
author Alain Mazy <alain@mazy.be>
date Wed, 29 Apr 2020 20:43:09 +0200
parents Framework/Radiography/RadiographyLayer.cpp@379c00958553
children 30deba7bc8e2
comparison
equal deleted inserted replaced
1397:1c2d065ba372 1398:c5403d52078c
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "RadiographyLayer.h"
23
24 #include <Core/OrthancException.h>
25
26
27 namespace OrthancStone
28 {
29 static double Square(double x)
30 {
31 return x * x;
32 }
33
34
35 RadiographyLayer::Geometry::Geometry() :
36 hasCrop_(false),
37 flipVertical_(false),
38 flipHorizontal_(false),
39 panX_(0),
40 panY_(0),
41 angle_(0),
42 resizeable_(false),
43 pixelSpacingX_(1),
44 pixelSpacingY_(1)
45 {
46
47 }
48
49 void RadiographyLayer::Geometry::GetCrop(unsigned int &x, unsigned int &y, unsigned int &width, unsigned int &height) const
50 {
51 if (!hasCrop_)
52 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); // you should probably use RadiographyLayer::GetCrop() or at least call HasCrop() before
53
54 x = cropX_;
55 y = cropY_;
56 width = cropWidth_;
57 height = cropHeight_;
58 }
59
60 void RadiographyLayer::UpdateTransform()
61 {
62 // important to update transform_ before getting the center to use the right scaling !!!
63 transform_ = AffineTransform2D::CreateScaling(geometry_.GetScalingX(), geometry_.GetScalingY());
64
65 double centerX, centerY;
66 GetCenter(centerX, centerY);
67
68 transform_ = AffineTransform2D::Combine(
69 AffineTransform2D::CreateOffset(geometry_.GetPanX(), geometry_.GetPanY()),
70 AffineTransform2D::CreateRotation(geometry_.GetAngle(), centerX, centerY),
71 transform_);
72
73 transformInverse_ = AffineTransform2D::Invert(transform_);
74 }
75
76
77 void RadiographyLayer::AddToExtent(Extent2D& extent,
78 double x,
79 double y) const
80 {
81 GetTransform().Apply(x, y);
82 extent.AddPoint(x, y);
83 }
84
85 bool RadiographyLayer::Contains(double x,
86 double y) const
87 {
88 GetTransformInverse().Apply(x, y);
89
90 unsigned int cropX, cropY, cropWidth, cropHeight;
91 GetCrop(cropX, cropY, cropWidth, cropHeight);
92
93 return (x >= cropX && x <= cropX + cropWidth &&
94 y >= cropY && y <= cropY + cropHeight);
95 }
96
97
98 void RadiographyLayer::DrawBorders(CairoContext& context,
99 double zoom)
100 {
101 if (GetControlPointCount() < 3 )
102 return;
103
104 cairo_t* cr = context.GetObject();
105 cairo_set_line_width(cr, 2.0 / zoom);
106
107 ControlPoint cp;
108 GetControlPoint(cp, 0);
109 cairo_move_to(cr, cp.x, cp.y);
110
111 for (size_t i = 0; i < GetControlPointCount(); i++)
112 {
113 GetControlPoint(cp, i);
114 cairo_line_to(cr, cp.x, cp.y);
115 }
116
117 cairo_close_path(cr);
118 cairo_stroke(cr);
119 }
120
121
122 RadiographyLayer::RadiographyLayer(const RadiographyScene& scene) :
123 index_(0),
124 hasSize_(false),
125 width_(0),
126 height_(0),
127 prefferedPhotometricDisplayMode_(RadiographyPhotometricDisplayMode_Default),
128 scene_(scene)
129 {
130 UpdateTransform();
131 }
132
133 void RadiographyLayer::ResetCrop()
134 {
135 geometry_.ResetCrop();
136 UpdateTransform();
137 }
138
139 void RadiographyLayer::SetPreferredPhotomotricDisplayMode(RadiographyPhotometricDisplayMode prefferedPhotometricDisplayMode)
140 {
141 prefferedPhotometricDisplayMode_ = prefferedPhotometricDisplayMode;
142
143 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
144 }
145
146 void RadiographyLayer::SetCrop(unsigned int x,
147 unsigned int y,
148 unsigned int width,
149 unsigned int height)
150 {
151 if (!hasSize_)
152 {
153 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
154 }
155
156 if (x + width > width_ ||
157 y + height > height_)
158 {
159 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
160 }
161
162 geometry_.SetCrop(x, y, width, height);
163 UpdateTransform();
164
165 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
166 }
167
168 void RadiographyLayer::SetGeometry(const Geometry& geometry)
169 {
170 geometry_ = geometry;
171
172 if (hasSize_)
173 {
174 UpdateTransform();
175 }
176
177 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
178 }
179
180
181 void RadiographyLayer::GetCrop(unsigned int& x,
182 unsigned int& y,
183 unsigned int& width,
184 unsigned int& height) const
185 {
186 if (GetGeometry().HasCrop())
187 {
188 GetGeometry().GetCrop(x, y, width, height);
189 }
190 else
191 {
192 x = 0;
193 y = 0;
194 width = width_;
195 height = height_;
196 }
197 }
198
199
200 void RadiographyLayer::SetAngle(double angle)
201 {
202 geometry_.SetAngle(angle);
203 UpdateTransform();
204
205 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
206 }
207
208 void RadiographyLayer::SetFlipVertical(bool flip)
209 {
210 geometry_.SetFlipVertical(flip);
211 UpdateTransform();
212
213 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
214 }
215
216 void RadiographyLayer::SetFlipHorizontal(bool flip)
217 {
218 geometry_.SetFlipHorizontal(flip);
219 UpdateTransform();
220
221 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
222 }
223
224 void RadiographyLayer::SetSize(unsigned int width,
225 unsigned int height,
226 bool emitLayerEditedEvent)
227 {
228 hasSize_ = true;
229 width_ = width;
230 height_ = height;
231
232 UpdateTransform();
233
234 if (emitLayerEditedEvent)
235 {
236 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
237 }
238 }
239
240 Extent2D RadiographyLayer::GetSceneExtent(bool /*minimal*/) const
241 {
242 Extent2D extent;
243
244 unsigned int x, y, width, height;
245 GetCrop(x, y, width, height);
246
247 double dx = static_cast<double>(x);
248 double dy = static_cast<double>(y);
249 double dwidth = static_cast<double>(width);
250 double dheight = static_cast<double>(height);
251
252 // AddToExtent transforms the coordinates from image to scene
253 AddToExtent(extent, dx, dy);
254 AddToExtent(extent, dx + dwidth, dy);
255 AddToExtent(extent, dx, dy + dheight);
256 AddToExtent(extent, dx + dwidth, dy + dheight);
257
258 return extent;
259 }
260
261
262 bool RadiographyLayer::GetPixel(unsigned int& imageX,
263 unsigned int& imageY,
264 double sceneX,
265 double sceneY) const
266 {
267 if (width_ == 0 ||
268 height_ == 0)
269 {
270 return false;
271 }
272 else
273 {
274 GetTransformInverse().Apply(sceneX, sceneY);
275
276 int x = static_cast<int>(std::floor(sceneX));
277 int y = static_cast<int>(std::floor(sceneY));
278
279 if (x < 0)
280 {
281 imageX = 0;
282 }
283 else if (x >= static_cast<int>(width_))
284 {
285 imageX = width_;
286 }
287 else
288 {
289 imageX = static_cast<unsigned int>(x);
290 }
291
292 if (y < 0)
293 {
294 imageY = 0;
295 }
296 else if (y >= static_cast<int>(height_))
297 {
298 imageY = height_;
299 }
300 else
301 {
302 imageY = static_cast<unsigned int>(y);
303 }
304
305 return true;
306 }
307 }
308
309
310 void RadiographyLayer::SetPan(double x,
311 double y)
312 {
313 geometry_.SetPan(x, y);
314 UpdateTransform();
315 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
316 }
317
318
319 void RadiographyLayer::SetPixelSpacing(double x,
320 double y,
321 bool emitLayerEditedEvent)
322 {
323 geometry_.SetPixelSpacing(x, y);
324 UpdateTransform();
325 if (emitLayerEditedEvent)
326 {
327 BroadcastMessage(RadiographyLayer::LayerEditedMessage(*this));
328 }
329 }
330
331
332 void RadiographyLayer::GetCenter(double& centerX,
333 double& centerY) const
334 {
335 centerX = static_cast<double>(width_) / 2.0;
336 centerY = static_cast<double>(height_) / 2.0;
337 GetTransform().Apply(centerX, centerY);
338 }
339
340
341
342 size_t RadiographyLayer::GetControlPointCount() const {return 4;}
343
344 void RadiographyLayer::GetControlPoint(ControlPoint& cpScene /* out in scene coordinates */,
345 size_t index) const
346 {
347 unsigned int cropX, cropY, cropWidth, cropHeight;
348 GetCrop(cropX, cropY, cropWidth, cropHeight);
349
350 ControlPoint cp;
351 switch (index)
352 {
353 case RadiographyControlPointType_TopLeftCorner:
354 cp = ControlPoint(cropX, cropY, RadiographyControlPointType_TopLeftCorner);
355 break;
356
357 case RadiographyControlPointType_TopRightCorner:
358 cp = ControlPoint(cropX + cropWidth, cropY, RadiographyControlPointType_TopRightCorner);
359 break;
360
361 case RadiographyControlPointType_BottomLeftCorner:
362 cp = ControlPoint(cropX, cropY + cropHeight, RadiographyControlPointType_BottomLeftCorner);
363 break;
364
365 case RadiographyControlPointType_BottomRightCorner:
366 cp = ControlPoint(cropX + cropWidth, cropY + cropHeight, RadiographyControlPointType_BottomRightCorner);
367 break;
368
369 default:
370 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
371 }
372
373 // transforms image coordinates into scene coordinates
374 GetTransform().Apply(cp.x, cp.y);
375 cpScene = cp;
376 }
377
378 bool RadiographyLayer::LookupControlPoint(ControlPoint& cpScene /* out */,
379 double x,
380 double y,
381 double zoom,
382 double viewportDistance) const
383 {
384 double threshold = Square(viewportDistance / zoom);
385
386 for (size_t i = 0; i < GetControlPointCount(); i++)
387 {
388 ControlPoint cp;
389 GetControlPoint(cp, i);
390
391 double d = Square(cp.x - x) + Square(cp.y - y);
392
393 if (d <= threshold)
394 {
395 cpScene = cp;
396 return true;
397 }
398 }
399
400 return false;
401 }
402 }