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 |
|
|
|