comparison Framework/Radiography/RadiographyLayerResizeTracker.cpp @ 415:c0589c3173fd

finished reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Nov 2018 10:36:53 +0100
parents
children b85f635f1eb5 b70e9be013e4
comparison
equal deleted inserted replaced
414:f7616c010056 415:c0589c3173fd
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-2018 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 "RadiographyLayerResizeTracker.h"
23
24 #include "RadiographySceneCommand.h"
25
26 #include <Core/OrthancException.h>
27
28 #include <boost/math/special_functions/round.hpp>
29
30
31 namespace OrthancStone
32 {
33 static double ComputeDistance(double x1,
34 double y1,
35 double x2,
36 double y2)
37 {
38 double dx = x1 - x2;
39 double dy = y1 - y2;
40 return sqrt(dx * dx + dy * dy);
41 }
42
43
44 class RadiographyLayerResizeTracker::UndoRedoCommand : public RadiographySceneCommand
45 {
46 private:
47 double sourceSpacingX_;
48 double sourceSpacingY_;
49 double sourcePanX_;
50 double sourcePanY_;
51 double targetSpacingX_;
52 double targetSpacingY_;
53 double targetPanX_;
54 double targetPanY_;
55
56 protected:
57 virtual void UndoInternal(RadiographyLayer& layer) const
58 {
59 layer.SetPixelSpacing(sourceSpacingX_, sourceSpacingY_);
60 layer.SetPan(sourcePanX_, sourcePanY_);
61 }
62
63 virtual void RedoInternal(RadiographyLayer& layer) const
64 {
65 layer.SetPixelSpacing(targetSpacingX_, targetSpacingY_);
66 layer.SetPan(targetPanX_, targetPanY_);
67 }
68
69 public:
70 UndoRedoCommand(const RadiographyLayerResizeTracker& tracker) :
71 RadiographySceneCommand(tracker.accessor_),
72 sourceSpacingX_(tracker.originalSpacingX_),
73 sourceSpacingY_(tracker.originalSpacingY_),
74 sourcePanX_(tracker.originalPanX_),
75 sourcePanY_(tracker.originalPanY_),
76 targetSpacingX_(tracker.accessor_.GetLayer().GetPixelSpacingX()),
77 targetSpacingY_(tracker.accessor_.GetLayer().GetPixelSpacingY()),
78 targetPanX_(tracker.accessor_.GetLayer().GetPanX()),
79 targetPanY_(tracker.accessor_.GetLayer().GetPanY())
80 {
81 }
82 };
83
84
85 RadiographyLayerResizeTracker::RadiographyLayerResizeTracker(UndoRedoStack& undoRedoStack,
86 RadiographyScene& scene,
87 size_t layer,
88 double x,
89 double y,
90 Corner corner,
91 bool roundScaling) :
92 undoRedoStack_(undoRedoStack),
93 accessor_(scene, layer),
94 roundScaling_(roundScaling)
95 {
96 if (accessor_.IsValid() &&
97 accessor_.GetLayer().IsResizeable())
98 {
99 originalSpacingX_ = accessor_.GetLayer().GetPixelSpacingX();
100 originalSpacingY_ = accessor_.GetLayer().GetPixelSpacingY();
101 originalPanX_ = accessor_.GetLayer().GetPanX();
102 originalPanY_ = accessor_.GetLayer().GetPanY();
103
104 switch (corner)
105 {
106 case Corner_TopLeft:
107 oppositeCorner_ = Corner_BottomRight;
108 break;
109
110 case Corner_TopRight:
111 oppositeCorner_ = Corner_BottomLeft;
112 break;
113
114 case Corner_BottomLeft:
115 oppositeCorner_ = Corner_TopRight;
116 break;
117
118 case Corner_BottomRight:
119 oppositeCorner_ = Corner_TopLeft;
120 break;
121
122 default:
123 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
124 }
125
126 accessor_.GetLayer().GetCorner(oppositeX_, oppositeY_, oppositeCorner_);
127
128 double d = ComputeDistance(x, y, oppositeX_, oppositeY_);
129 if (d >= std::numeric_limits<float>::epsilon())
130 {
131 baseScaling_ = 1.0 / d;
132 }
133 else
134 {
135 // Avoid division by zero in extreme cases
136 accessor_.Invalidate();
137 }
138 }
139 }
140
141
142 void RadiographyLayerResizeTracker::Render(CairoContext& context,
143 double zoom)
144 {
145 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
146 }
147
148
149 void RadiographyLayerResizeTracker::MouseUp()
150 {
151 if (accessor_.IsValid() &&
152 accessor_.GetLayer().IsResizeable())
153 {
154 undoRedoStack_.Add(new UndoRedoCommand(*this));
155 }
156 }
157
158
159 void RadiographyLayerResizeTracker::MouseMove(int displayX,
160 int displayY,
161 double sceneX,
162 double sceneY)
163 {
164 static const double ROUND_SCALING = 0.1;
165
166 if (accessor_.IsValid() &&
167 accessor_.GetLayer().IsResizeable())
168 {
169 double scaling = ComputeDistance(oppositeX_, oppositeY_, sceneX, sceneY) * baseScaling_;
170
171 if (roundScaling_)
172 {
173 scaling = boost::math::round<double>((scaling / ROUND_SCALING) * ROUND_SCALING);
174 }
175
176 RadiographyLayer& layer = accessor_.GetLayer();
177 layer.SetPixelSpacing(scaling * originalSpacingX_,
178 scaling * originalSpacingY_);
179
180 // Keep the opposite corner at a fixed location
181 double ox, oy;
182 layer.GetCorner(ox, oy, oppositeCorner_);
183 layer.SetPan(layer.GetPanX() + oppositeX_ - ox,
184 layer.GetPanY() + oppositeY_ - oy);
185 }
186 }
187 }