v2.0.0
Loading...
Searching...
No Matches
sliceobject.cpp
Go to the documentation of this file.
1//=============================================================================================================
12
13//=============================================================================================================
14// INCLUDES
15//=============================================================================================================
16
17#include "sliceobject.h"
18
19//=============================================================================================================
20// USED NAMESPACES
21//=============================================================================================================
22
23using namespace DISP3DLIB;
24
25//=============================================================================================================
26// DEFINE MEMBER METHODS
27//=============================================================================================================
28
30: m_corner00(Eigen::Vector3d::Zero())
31, m_corner10(Eigen::Vector3d::UnitX())
32, m_corner01(Eigen::Vector3d::UnitY())
33, m_corner11(Eigen::Vector3d::UnitX() + Eigen::Vector3d::UnitY())
34{
35}
36
37//=============================================================================================================
38
39void SliceObject::setSlice(const QImage& image,
41 int sliceIndex,
42 const Eigen::Matrix4d& voxelToWorld)
43{
44 m_image = image;
45 m_orientation = orientation;
46 m_sliceIndex = sliceIndex;
47 m_voxelToWorld = voxelToWorld;
48
49 // Image dimensions define the number of voxels along each in-plane axis.
50 const int w = m_image.width();
51 const int h = m_image.height();
52
53 // Build the four corner positions in voxel coordinates, then transform to world.
54 // u runs along image columns, v along image rows.
55 // The switch below assigns all four, but the compiler cannot prove the
56 // enumeration is exhaustive, so start from a defined value.
57 Eigen::Vector4d c00 = Eigen::Vector4d::Zero();
58 Eigen::Vector4d c10 = Eigen::Vector4d::Zero();
59 Eigen::Vector4d c01 = Eigen::Vector4d::Zero();
60 Eigen::Vector4d c11 = Eigen::Vector4d::Zero();
61
62 switch (m_orientation) {
64 // u → X, v → Y, slice along Z
65 c00 << 0, 0, sliceIndex, 1;
66 c10 << w, 0, sliceIndex, 1;
67 c01 << 0, h, sliceIndex, 1;
68 c11 << w, h, sliceIndex, 1;
69 break;
71 // u → X, v → Z, slice along Y
72 c00 << 0, sliceIndex, 0, 1;
73 c10 << w, sliceIndex, 0, 1;
74 c01 << 0, sliceIndex, h, 1;
75 c11 << w, sliceIndex, h, 1;
76 break;
78 // u → Y, v → Z, slice along X
79 c00 << sliceIndex, 0, 0, 1;
80 c10 << sliceIndex, w, 0, 1;
81 c01 << sliceIndex, 0, h, 1;
82 c11 << sliceIndex, w, h, 1;
83 break;
84 }
85
86 // Transform voxel → world (RAS)
87 Eigen::Vector4d w00 = m_voxelToWorld * c00;
88 Eigen::Vector4d w10 = m_voxelToWorld * c10;
89 Eigen::Vector4d w01 = m_voxelToWorld * c01;
90 Eigen::Vector4d w11 = m_voxelToWorld * c11;
91
92 m_corner00 = w00.head<3>();
93 m_corner10 = w10.head<3>();
94 m_corner01 = w01.head<3>();
95 m_corner11 = w11.head<3>();
96}
97
98//=============================================================================================================
99
102 int sliceIndex,
103 const Eigen::Matrix4d& imageToWorld)
104{
105 m_image = image;
106 m_orientation = orientation;
107 m_sliceIndex = sliceIndex;
108
109 const int w = m_image.width();
110 const int h = m_image.height();
111
112 const Eigen::Vector4d c00(0.0, 0.0, 0.0, 1.0);
113 const Eigen::Vector4d c10(static_cast<double>(w), 0.0, 0.0, 1.0);
114 const Eigen::Vector4d c01(0.0, static_cast<double>(h), 0.0, 1.0);
115 const Eigen::Vector4d c11(static_cast<double>(w), static_cast<double>(h), 0.0, 1.0);
116
117 m_corner00 = (imageToWorld * c00).head<3>();
118 m_corner10 = (imageToWorld * c10).head<3>();
119 m_corner01 = (imageToWorld * c01).head<3>();
120 m_corner11 = (imageToWorld * c11).head<3>();
121}
122
123//=============================================================================================================
124
126{
127 return m_orientation;
128}
129
130//=============================================================================================================
131
133{
134 return m_sliceIndex;
135}
136
137//=============================================================================================================
138
139const QImage& SliceObject::image() const
140{
141 return m_image;
142}
143
144//=============================================================================================================
145
147{
148 // Build a 4×4 matrix that maps the unit quad [0,1]² to the world-space quad.
149 // Column 0: edge along u (corner10 – corner00)
150 // Column 1: edge along v (corner01 – corner00)
151 // Column 3: translation (corner00)
152 Eigen::Vector3d u = m_corner10 - m_corner00;
153 Eigen::Vector3d v = m_corner01 - m_corner00;
154 Eigen::Vector3d n = u.cross(v).normalized();
155
156 QMatrix4x4 mat;
157 mat.setToIdentity();
158 mat(0, 0) = static_cast<float>(u.x());
159 mat(1, 0) = static_cast<float>(u.y());
160 mat(2, 0) = static_cast<float>(u.z());
161
162 mat(0, 1) = static_cast<float>(v.x());
163 mat(1, 1) = static_cast<float>(v.y());
164 mat(2, 1) = static_cast<float>(v.z());
165
166 mat(0, 2) = static_cast<float>(n.x());
167 mat(1, 2) = static_cast<float>(n.y());
168 mat(2, 2) = static_cast<float>(n.z());
169
170 mat(0, 3) = static_cast<float>(m_corner00.x());
171 mat(1, 3) = static_cast<float>(m_corner00.y());
172 mat(2, 3) = static_cast<float>(m_corner00.z());
173
174 return mat;
175}
176
177//=============================================================================================================
178
179void SliceObject::setWindowLevel(float center, float width)
180{
181 m_windowCenter = center;
182 m_windowWidth = width;
183}
184
185//=============================================================================================================
186
188{
189 return m_windowCenter;
190}
191
192//=============================================================================================================
193
195{
196 return m_windowWidth;
197}
198
199//=============================================================================================================
200
202{
203 m_opacity = opacity;
204}
205
206//=============================================================================================================
207
209{
210 return m_opacity;
211}
212
213//=============================================================================================================
214
215void SliceObject::generateQuadVertices(QVector<float>& vertices) const
216{
217 // 4 vertices: pos(3) + uv(2) = 5 floats each → 20 floats total
218 vertices.resize(20);
219 float* p = vertices.data();
220
221 // Vertex 0: corner00, uv(0,0)
222 *p++ = static_cast<float>(m_corner00.x());
223 *p++ = static_cast<float>(m_corner00.y());
224 *p++ = static_cast<float>(m_corner00.z());
225 *p++ = 0.0f;
226 *p++ = 0.0f;
227
228 // Vertex 1: corner10, uv(1,0)
229 *p++ = static_cast<float>(m_corner10.x());
230 *p++ = static_cast<float>(m_corner10.y());
231 *p++ = static_cast<float>(m_corner10.z());
232 *p++ = 1.0f;
233 *p++ = 0.0f;
234
235 // Vertex 2: corner01, uv(0,1)
236 *p++ = static_cast<float>(m_corner01.x());
237 *p++ = static_cast<float>(m_corner01.y());
238 *p++ = static_cast<float>(m_corner01.z());
239 *p++ = 0.0f;
240 *p++ = 1.0f;
241
242 // Vertex 3: corner11, uv(1,1)
243 *p++ = static_cast<float>(m_corner11.x());
244 *p++ = static_cast<float>(m_corner11.y());
245 *p++ = static_cast<float>(m_corner11.z());
246 *p++ = 1.0f;
247 *p++ = 1.0f;
248}
249
250//=============================================================================================================
251
252void SliceObject::generateQuadIndices(QVector<unsigned int>& indices)
253{
254 // Two triangles: (0,1,2) and (2,1,3)
255 indices = {0, 1, 2, 2, 1, 3};
256}
Single MRI volume slice rendered as a textured quad with adjustable axis, position,...
3-D brain visualisation using the Qt RHI rendering backend.
SliceOrientation
Orientation for an orthogonal MRI slice.
Definition sliceobject.h:61
float windowCenter() const
const QImage & image() const
void setWindowLevel(float center, float width)
static void generateQuadIndices(QVector< unsigned int > &indices)
float windowWidth() const
QMatrix4x4 sliceToWorld() const
void setSlice(const QImage &image, SliceOrientation orientation, int sliceIndex, const Eigen::Matrix4d &voxelToWorld)
void setSliceToWorld(const QImage &image, SliceOrientation orientation, int sliceIndex, const Eigen::Matrix4d &imageToWorld)
void generateQuadVertices(QVector< float > &vertices) const
SliceOrientation orientation() const
void setOpacity(float opacity)