GCC Code Coverage Report


./
File: modules/viz/scene3d/adaptor/negato2d_camera.hpp
Date: 2025-01-21 16:21:04
Lines:
2/2
100.0%
Functions:
5/6
83.3%
Branches:
4/9
44.4%

Line Branch Exec Source
1 /************************************************************************
2 *
3 * Copyright (C) 2019-2024 IRCAD France
4 * Copyright (C) 2019-2020 IHU Strasbourg
5 *
6 * This file is part of Sight.
7 *
8 * Sight is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Sight is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
20 *
21 ***********************************************************************/
22
23 #pragma once
24
25 #include <data/helper/medical_image.hpp>
26
27 #include <viz/scene3d/adaptor.hpp>
28
29 #include <memory>
30
31 namespace sight::module::viz::scene3d::adaptor
32 {
33
34 /**
35 * @brief This adaptor lets the user move an orthographic camera to visualize medical images in 2D.
36 *
37 * The camera can be moved along its screen plane and zoom on a precise scene location.
38 * For more convenience this adaptor can make use of an optional input image to reset the camera's orientation
39 * when the image's slice type changes.
40 * Although this service was designed with negato visualization in mind, it could be used to render regular scenes
41 * from a 2D orthographic perspective.
42 *
43 * @warning may not work as intended when used with another camera adaptor on the same layer and must be started
44 * after all others one.
45 *
46 * @section Slots Slots
47 * - \b reset_camera(): zooms out the camera to see the whole scene.
48 * - \b changeOrientation(int,int): sets the camera's orientation to one of the image's axes.
49 *
50 * @section XML XML Configuration
51 * @code{.xml}
52 <service type="sight::module::viz::scene3d::adaptor::negato2d_camera" >
53 <inout key="image" uid="..." auto_connect="true" />
54 <inout key="tf" uid="..." />
55 <config priority="0" layerOrderDependant="true" orientation="sagittal" margin="0.1" block_width_scaling="true"/>
56 </service>
57 @endcode
58 *
59 * @subsection In-Out In-Out
60 * - \b image [sight::data::image](mandatory): image viewed in negato mode, used for auto connections only.
61 * Modification signals can be used to reset the camera's position and orientation. Useless without
62 * auto_connect="true".
63 * - \b tf [sight::data::transfer_function] (optional): the current TransferFunction. If it is not defined, we use the
64 * image's default transferFunction (CT-GreyLevel).
65 *
66 * @subsection Configuration Configuration:
67 * - \b priority (optional, int, default=0): interaction priority, higher priority interactions are performed first.
68 * - \b layerOrderDependant (optional, bool, default=true): define if interaction must take into account above layers.
69 * - \b orientation (optional, sagittal/frontal/axial, default=sagittal): the camera's orientation at start.
70 * - \b margin (optional, default=0.1): margin to the border of the viewport, in percentage of the highest of width
71 * or height.
72 * - \b scale (optional, default=false):whether to scale the orthographic plane to the viewport or
73 * keep it at its original resolution.
74 * - \b interactive (optional, default=true), enable or disable interactions.
75 */
76 class negato2d_camera final : public sight::viz::scene3d::adaptor,
77 public sight::viz::scene3d::interactor::base
78 {
79 public:
80
81 /// Generates default methods as New, dynamicCast, ...
82
4/9
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 814 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
2400 SIGHT_DECLARE_SERVICE(negato2d_camera, sight::viz::scene3d::adaptor);
83
84 /// Creates the service and initializes slots.
85 negato2d_camera() noexcept;
86
87 /// Destroys the adaptor.
88 64 ~negato2d_camera() noexcept override = default;
89
90 /**
91 * @brief Moving along slices (SHIFT to speed-up) or Zooms in the scene at the current cursor position.
92 * @param _delta distance that the wheel is rotated.
93 * @param _x current width coordinate of the mouse cursor.
94 * @param _y current height coordinate of the mouse cursor.
95 */
96 void wheel_event(modifier /*_modifier*/, double _delta, int _x, int _y) final;
97
98 /**
99 * @brief Zooms in the scene at the current cursor position.
100 * @param _scale_factor distance of the fingers
101 * @param _center_x the width coordinate of the center of the pinch
102 * @param _center_y the height coordinate of the center of the pinch
103 */
104 void pinch_gesture_event(double _scale_factor, int _center_x, int _center_y) final;
105
106 /**
107 * @brief Moves the camera along the projection plane.
108 * @param _x the last width coordinate of the finger
109 * @param _y the last height coordinate of the finger
110 * @param _dx width displacement of the finger since the last event.
111 * @param _dy height displacement of the finger since the last event.
112 */
113 void pan_gesture_move_event(int _x, int _y, int _dx, int _dy) final;
114
115 /**
116 * @brief Ends Moving the camera along the projection plane.
117 * @param _x the last width coordinate of the finger
118 * @param _y the last height coordinate of the finger
119 * @param _dx width displacement of the finger since the last event.
120 * @param _dy height displacement of the finger since the last event.
121 */
122 void pan_gesture_release_event(int _x, int _y, int _dx, int _dy) final;
123
124 /**
125 * @brief Interacts with the negato if it was picked by pressing any mouse button.
126 *
127 * Interactions will take place while holding down the button. The following actions are available:
128 * - Middle mouse click: moves the camera along the projection plane.
129 * - Right mouse click: adjust the transfer function level and window by moving
130 * the mouse up/down and left/right respectively.
131 *
132 * @param _button mouse button pressed.
133 * @param _x current width coordinate of the mouse cursor.
134 * @param _y current height coordinate of the mouse cursor.
135 */
136 void mouse_move_event(
137 sight::viz::scene3d::interactor::base::mouse_button _button,
138 modifier /*_mods*/,
139 int _x,
140 int _y,
141 int _dx,
142 int _dy
143 ) final;
144
145 /**
146 * @brief Verifies if the button is pressed within the camera's viewport and enables mouse movements if that is the
147 * case.
148 * @param _button mouse button pressed.
149 * @param _x current width coordinate of the mouse cursor.
150 * @param _y current height coordinate of the mouse cursor.
151 */
152 void button_press_event(
153 sight::viz::scene3d::interactor::base::mouse_button _button,
154 modifier /*_mods*/,
155 int _x,
156 int _y
157 ) final;
158
159 /**
160 * @brief Disables mouse movements.
161 * @param _button mouse button pressed.
162 * @param _x current width coordinate of the mouse cursor.
163 * @param _y current height coordinate of the mouse cursor.
164 */
165 void button_release_event(
166 sight::viz::scene3d::interactor::base::mouse_button _button,
167 modifier /*_mods*/,
168 int _x,
169 int _y
170 ) final;
171
172 /**
173 * @brief Resets the camera when the 'R' key is pressed.
174 * @param _key key button pressed.
175 * @param _x current width coordinate of the mouse cursor.
176 * @param _y current height coordinate of the mouse cursor.
177 */
178 void key_press_event(int _key, modifier /*_mods*/, int _x, int _y) final;
179
180 protected:
181
182 /// Configures the layer, interaction priority and camera orientation.
183 void configuring() final;
184
185 /// Adds negato camera interactions to the layer.
186 void starting() final;
187
188 /**
189 * @brief Proposals to connect service slots to associated object signals.
190 * @return A map of each proposed connection.
191 *
192 * Connect data::image::MODIFIED_SIG of s_IMAGE_INPUT to RESET_CAMERA_SLOT
193 * Connect data::image::SLICE_TYPE_MODIFIED_SIG of s_IMAGE_INPUT to CHANGE_ORIENTATION_SLOT
194 * Connect data::image::SLICE_INDEX_MODIFIED_SIG of s_IMAGE_INPUT to MOVE_BACK_SLOT
195 */
196 service::connections_t auto_connections() const final;
197
198 /// Does nothing.
199 void updating() noexcept final;
200
201 /// Removes negato camera interactions from the layer.
202 void stopping() final;
203
204 private:
205
206 using axis_t = data::helper::medical_image::axis_t;
207
208 /// SLOT: resets the camera's zoom.
209 void reset_camera();
210
211 /// SLOT: resets the display when resizing.
212 void resize_viewport();
213
214 /**
215 * @brief SLOT: sets the camera's orientation to one of the image's axes.
216 * @param _from origin of the orientation.
217 * @param _to destination of the orientation.
218 */
219 void change_orientation(int _from, int _to);
220
221 /// Updates the transfer function window and level by adding the input values.
222 void update_windowing(double _dw, double _dl);
223
224 /// Get the inverse transformation matrix from camera to origin
225 Ogre::Matrix4 get_camera_to_origin_transform() const;
226
227 /// Defines the current interaction status.
228 bool m_is_interacting {false};
229
230 /// Defines the image current orientation.
231 axis_t m_axis {axis_t::z_axis};
232
233 /// Defines the interaction priority.
234 int m_priority {0};
235
236 /// Defines the transfer function window value at the time the interaction started.
237 double m_initial_window {0.F};
238
239 /// Defines the transfer function level value at the time the interaction started.
240 double m_initial_level {0.F};
241
242 /// Defines the mouse position at the time the windowing interaction started.
243 Ogre::Vector2i m_initial_pos {-1, -1};
244
245 /// Defines the margin to the border of the viewport.
246 float m_margin {0.1F};
247
248 /// This allows us to reset the camera when Qt refreshes the size of the viewport after the start of the adaptor
249 bool m_has_moved {false};
250
251 /// Enable/disable scaling (like video adaptor).
252 bool m_scale {false};
253
254 /// Enable/disable interactions.
255 bool m_is_interactive {true};
256
257 /// Handles connection with the layer.
258 core::com::helper::sig_slot_connection m_layer_connection;
259
260 static constexpr std::string_view IMAGE_INOUT = "image";
261 static constexpr std::string_view TF_INOUT = "tf";
262
263 sight::data::ptr<sight::data::image, sight::data::access::inout> m_image {this, IMAGE_INOUT};
264 sight::data::ptr<sight::data::transfer_function, sight::data::access::inout> m_tf {this, TF_INOUT, true};
265 };
266
267 } // namespace sight::module::viz::scene3d::adaptor.
268