Mercurial > hg > orthanc-stone
comparison Applications/Samples/SingleFrameEditorApplication.h @ 414:f7616c010056
reorganization
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 12 Nov 2018 18:00:48 +0100 |
parents | 18b707fb8620 |
children | c0589c3173fd |
comparison
equal
deleted
inserted
replaced
413:18b707fb8620 | 414:f7616c010056 |
---|---|
21 | 21 |
22 #pragma once | 22 #pragma once |
23 | 23 |
24 #include "SampleApplicationBase.h" | 24 #include "SampleApplicationBase.h" |
25 | 25 |
26 #include "../../Framework/Radiography/RadiographyLayerMoveTracker.h" | |
27 #include "../../Framework/Radiography/RadiographyLayerRotateTracker.h" | |
26 #include "../../Framework/Radiography/RadiographyScene.h" | 28 #include "../../Framework/Radiography/RadiographyScene.h" |
29 #include "../../Framework/Radiography/RadiographySceneCommand.h" | |
27 #include "../../Framework/Radiography/RadiographyWidget.h" | 30 #include "../../Framework/Radiography/RadiographyWidget.h" |
28 | 31 |
29 #include "../../Framework/Toolbox/UndoRedoStack.h" | 32 #include "../../Framework/Toolbox/UndoRedoStack.h" |
30 | 33 |
31 #include <Core/Images/FontRegistry.h> | 34 #include <Core/Images/FontRegistry.h> |
44 // Export using PAM is faster than using PNG, but requires Orthanc | 47 // Export using PAM is faster than using PNG, but requires Orthanc |
45 // core >= 1.4.3 | 48 // core >= 1.4.3 |
46 #define EXPORT_USING_PAM 1 | 49 #define EXPORT_USING_PAM 1 |
47 | 50 |
48 | 51 |
49 #include <boost/math/constants/constants.hpp> | |
50 #include <boost/math/special_functions/round.hpp> | 52 #include <boost/math/special_functions/round.hpp> |
51 | 53 |
52 | 54 |
53 namespace OrthancStone | 55 namespace OrthancStone |
54 { | 56 { |
55 class RadiographySceneCommand : public UndoRedoStack::ICommand | |
56 { | |
57 private: | |
58 RadiographyScene& scene_; | |
59 size_t layer_; | |
60 | |
61 protected: | |
62 virtual void UndoInternal(RadiographyLayer& layer) const = 0; | |
63 | |
64 virtual void RedoInternal(RadiographyLayer& layer) const = 0; | |
65 | |
66 public: | |
67 RadiographySceneCommand(RadiographyScene& scene, | |
68 size_t layer) : | |
69 scene_(scene), | |
70 layer_(layer) | |
71 { | |
72 } | |
73 | |
74 RadiographySceneCommand(const RadiographyScene::LayerAccessor& accessor) : | |
75 scene_(accessor.GetScene()), | |
76 layer_(accessor.GetIndex()) | |
77 { | |
78 } | |
79 | |
80 virtual void Undo() const | |
81 { | |
82 RadiographyScene::LayerAccessor accessor(scene_, layer_); | |
83 | |
84 if (accessor.IsValid()) | |
85 { | |
86 UndoInternal(accessor.GetLayer()); | |
87 } | |
88 } | |
89 | |
90 virtual void Redo() const | |
91 { | |
92 RadiographyScene::LayerAccessor accessor(scene_, layer_); | |
93 | |
94 if (accessor.IsValid()) | |
95 { | |
96 RedoInternal(accessor.GetLayer()); | |
97 } | |
98 } | |
99 }; | |
100 | |
101 | |
102 class RadiographyLayerRotateTracker : public IWorldSceneMouseTracker | |
103 { | |
104 private: | |
105 UndoRedoStack& undoRedoStack_; | |
106 RadiographyScene::LayerAccessor accessor_; | |
107 double centerX_; | |
108 double centerY_; | |
109 double originalAngle_; | |
110 double clickAngle_; | |
111 bool roundAngles_; | |
112 | |
113 bool ComputeAngle(double& angle /* out */, | |
114 double sceneX, | |
115 double sceneY) const | |
116 { | |
117 Vector u; | |
118 LinearAlgebra::AssignVector(u, sceneX - centerX_, sceneY - centerY_); | |
119 | |
120 double nu = boost::numeric::ublas::norm_2(u); | |
121 | |
122 if (!LinearAlgebra::IsCloseToZero(nu)) | |
123 { | |
124 u /= nu; | |
125 angle = atan2(u[1], u[0]); | |
126 return true; | |
127 } | |
128 else | |
129 { | |
130 return false; | |
131 } | |
132 } | |
133 | |
134 | |
135 class UndoRedoCommand : public RadiographySceneCommand | |
136 { | |
137 private: | |
138 double sourceAngle_; | |
139 double targetAngle_; | |
140 | |
141 static int ToDegrees(double angle) | |
142 { | |
143 return boost::math::iround(angle * 180.0 / boost::math::constants::pi<double>()); | |
144 } | |
145 | |
146 protected: | |
147 virtual void UndoInternal(RadiographyLayer& layer) const | |
148 { | |
149 LOG(INFO) << "Undo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; | |
150 layer.SetAngle(sourceAngle_); | |
151 } | |
152 | |
153 virtual void RedoInternal(RadiographyLayer& layer) const | |
154 { | |
155 LOG(INFO) << "Redo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; | |
156 layer.SetAngle(targetAngle_); | |
157 } | |
158 | |
159 public: | |
160 UndoRedoCommand(const RadiographyLayerRotateTracker& tracker) : | |
161 RadiographySceneCommand(tracker.accessor_), | |
162 sourceAngle_(tracker.originalAngle_), | |
163 targetAngle_(tracker.accessor_.GetLayer().GetAngle()) | |
164 { | |
165 } | |
166 }; | |
167 | |
168 | |
169 public: | |
170 RadiographyLayerRotateTracker(UndoRedoStack& undoRedoStack, | |
171 RadiographyScene& scene, | |
172 const ViewportGeometry& view, | |
173 size_t layer, | |
174 double x, | |
175 double y, | |
176 bool roundAngles) : | |
177 undoRedoStack_(undoRedoStack), | |
178 accessor_(scene, layer), | |
179 roundAngles_(roundAngles) | |
180 { | |
181 if (accessor_.IsValid()) | |
182 { | |
183 accessor_.GetLayer().GetCenter(centerX_, centerY_); | |
184 originalAngle_ = accessor_.GetLayer().GetAngle(); | |
185 | |
186 double sceneX, sceneY; | |
187 view.MapDisplayToScene(sceneX, sceneY, x, y); | |
188 | |
189 if (!ComputeAngle(clickAngle_, x, y)) | |
190 { | |
191 accessor_.Invalidate(); | |
192 } | |
193 } | |
194 } | |
195 | |
196 virtual bool HasRender() const | |
197 { | |
198 return false; | |
199 } | |
200 | |
201 virtual void Render(CairoContext& context, | |
202 double zoom) | |
203 { | |
204 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
205 } | |
206 | |
207 virtual void MouseUp() | |
208 { | |
209 if (accessor_.IsValid()) | |
210 { | |
211 undoRedoStack_.Add(new UndoRedoCommand(*this)); | |
212 } | |
213 } | |
214 | |
215 virtual void MouseMove(int displayX, | |
216 int displayY, | |
217 double sceneX, | |
218 double sceneY) | |
219 { | |
220 static const double ROUND_ANGLE = 15.0 / 180.0 * boost::math::constants::pi<double>(); | |
221 | |
222 double angle; | |
223 | |
224 if (accessor_.IsValid() && | |
225 ComputeAngle(angle, sceneX, sceneY)) | |
226 { | |
227 angle = angle - clickAngle_ + originalAngle_; | |
228 | |
229 if (roundAngles_) | |
230 { | |
231 angle = boost::math::round<double>((angle / ROUND_ANGLE) * ROUND_ANGLE); | |
232 } | |
233 | |
234 accessor_.GetLayer().SetAngle(angle); | |
235 } | |
236 } | |
237 }; | |
238 | |
239 | |
240 class RadiographyLayerMoveTracker : public IWorldSceneMouseTracker | |
241 { | |
242 private: | |
243 UndoRedoStack& undoRedoStack_; | |
244 RadiographyScene::LayerAccessor accessor_; | |
245 double clickX_; | |
246 double clickY_; | |
247 double panX_; | |
248 double panY_; | |
249 bool oneAxis_; | |
250 | |
251 class UndoRedoCommand : public RadiographySceneCommand | |
252 { | |
253 private: | |
254 double sourceX_; | |
255 double sourceY_; | |
256 double targetX_; | |
257 double targetY_; | |
258 | |
259 protected: | |
260 virtual void UndoInternal(RadiographyLayer& layer) const | |
261 { | |
262 layer.SetPan(sourceX_, sourceY_); | |
263 } | |
264 | |
265 virtual void RedoInternal(RadiographyLayer& layer) const | |
266 { | |
267 layer.SetPan(targetX_, targetY_); | |
268 } | |
269 | |
270 public: | |
271 UndoRedoCommand(const RadiographyLayerMoveTracker& tracker) : | |
272 RadiographySceneCommand(tracker.accessor_), | |
273 sourceX_(tracker.panX_), | |
274 sourceY_(tracker.panY_), | |
275 targetX_(tracker.accessor_.GetLayer().GetPanX()), | |
276 targetY_(tracker.accessor_.GetLayer().GetPanY()) | |
277 { | |
278 } | |
279 }; | |
280 | |
281 | |
282 public: | |
283 RadiographyLayerMoveTracker(UndoRedoStack& undoRedoStack, | |
284 RadiographyScene& scene, | |
285 size_t layer, | |
286 double x, | |
287 double y, | |
288 bool oneAxis) : | |
289 undoRedoStack_(undoRedoStack), | |
290 accessor_(scene, layer), | |
291 clickX_(x), | |
292 clickY_(y), | |
293 oneAxis_(oneAxis) | |
294 { | |
295 if (accessor_.IsValid()) | |
296 { | |
297 panX_ = accessor_.GetLayer().GetPanX(); | |
298 panY_ = accessor_.GetLayer().GetPanY(); | |
299 } | |
300 } | |
301 | |
302 virtual bool HasRender() const | |
303 { | |
304 return false; | |
305 } | |
306 | |
307 virtual void Render(CairoContext& context, | |
308 double zoom) | |
309 { | |
310 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
311 } | |
312 | |
313 virtual void MouseUp() | |
314 { | |
315 if (accessor_.IsValid()) | |
316 { | |
317 undoRedoStack_.Add(new UndoRedoCommand(*this)); | |
318 } | |
319 } | |
320 | |
321 virtual void MouseMove(int displayX, | |
322 int displayY, | |
323 double sceneX, | |
324 double sceneY) | |
325 { | |
326 if (accessor_.IsValid()) | |
327 { | |
328 double dx = sceneX - clickX_; | |
329 double dy = sceneY - clickY_; | |
330 | |
331 if (oneAxis_) | |
332 { | |
333 if (fabs(dx) > fabs(dy)) | |
334 { | |
335 accessor_.GetLayer().SetPan(dx + panX_, panY_); | |
336 } | |
337 else | |
338 { | |
339 accessor_.GetLayer().SetPan(panX_, dy + panY_); | |
340 } | |
341 } | |
342 else | |
343 { | |
344 accessor_.GetLayer().SetPan(dx + panX_, dy + panY_); | |
345 } | |
346 } | |
347 } | |
348 }; | |
349 | |
350 | |
351 class RadiographyLayerCropTracker : public IWorldSceneMouseTracker | 57 class RadiographyLayerCropTracker : public IWorldSceneMouseTracker |
352 { | 58 { |
353 private: | 59 private: |
354 UndoRedoStack& undoRedoStack_; | 60 UndoRedoStack& undoRedoStack_; |
355 RadiographyScene::LayerAccessor accessor_; | 61 RadiographyScene::LayerAccessor accessor_; |