v2.0.0
Loading...
Searching...
No Matches
sliceobject.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "sliceobject.h"
40
41//=============================================================================================================
42// USED NAMESPACES
43//=============================================================================================================
44
45using namespace DISP3DLIB;
46
47//=============================================================================================================
48// DEFINE MEMBER METHODS
49//=============================================================================================================
50
52 : m_corner00(Eigen::Vector3d::Zero())
53 , m_corner10(Eigen::Vector3d::UnitX())
54 , m_corner01(Eigen::Vector3d::UnitY())
55 , m_corner11(Eigen::Vector3d::UnitX() + Eigen::Vector3d::UnitY())
56{
57}
58
59//=============================================================================================================
60
61void SliceObject::setSlice(const QImage& image,
63 int sliceIndex,
64 const Eigen::Matrix4d& voxelToWorld)
65{
66 m_image = image;
67 m_orientation = orientation;
68 m_sliceIndex = sliceIndex;
69 m_voxelToWorld = voxelToWorld;
70
71 // Image dimensions define the number of voxels along each in-plane axis.
72 const int w = m_image.width();
73 const int h = m_image.height();
74
75 // Build the four corner positions in voxel coordinates, then transform to world.
76 // u runs along image columns, v along image rows.
77 Eigen::Vector4d c00, c10, c01, c11;
78
79 switch (m_orientation) {
81 // u → X, v → Y, slice along Z
82 c00 << 0, 0, sliceIndex, 1;
83 c10 << w, 0, sliceIndex, 1;
84 c01 << 0, h, sliceIndex, 1;
85 c11 << w, h, sliceIndex, 1;
86 break;
88 // u → Y, v → Z, slice along X
89 c00 << sliceIndex, 0, 0, 1;
90 c10 << sliceIndex, w, 0, 1;
91 c01 << sliceIndex, 0, h, 1;
92 c11 << sliceIndex, w, h, 1;
93 break;
95 // u → X, v → Z, slice along Y
96 c00 << 0, sliceIndex, 0, 1;
97 c10 << w, sliceIndex, 0, 1;
98 c01 << 0, sliceIndex, h, 1;
99 c11 << w, sliceIndex, h, 1;
100 break;
101 }
102
103 // Transform voxel → world (RAS)
104 Eigen::Vector4d w00 = m_voxelToWorld * c00;
105 Eigen::Vector4d w10 = m_voxelToWorld * c10;
106 Eigen::Vector4d w01 = m_voxelToWorld * c01;
107 Eigen::Vector4d w11 = m_voxelToWorld * c11;
108
109 m_corner00 = w00.head<3>();
110 m_corner10 = w10.head<3>();
111 m_corner01 = w01.head<3>();
112 m_corner11 = w11.head<3>();
113}
114
115//=============================================================================================================
116
118{
119 return m_orientation;
120}
121
122//=============================================================================================================
123
125{
126 return m_sliceIndex;
127}
128
129//=============================================================================================================
130
131const QImage& SliceObject::image() const
132{
133 return m_image;
134}
135
136//=============================================================================================================
137
139{
140 // Build a 4×4 matrix that maps the unit quad [0,1]² to the world-space quad.
141 // Column 0: edge along u (corner10 – corner00)
142 // Column 1: edge along v (corner01 – corner00)
143 // Column 3: translation (corner00)
144 Eigen::Vector3d u = m_corner10 - m_corner00;
145 Eigen::Vector3d v = m_corner01 - m_corner00;
146 Eigen::Vector3d n = u.cross(v).normalized();
147
148 QMatrix4x4 mat;
149 mat.setToIdentity();
150 mat(0, 0) = static_cast<float>(u.x());
151 mat(1, 0) = static_cast<float>(u.y());
152 mat(2, 0) = static_cast<float>(u.z());
153
154 mat(0, 1) = static_cast<float>(v.x());
155 mat(1, 1) = static_cast<float>(v.y());
156 mat(2, 1) = static_cast<float>(v.z());
157
158 mat(0, 2) = static_cast<float>(n.x());
159 mat(1, 2) = static_cast<float>(n.y());
160 mat(2, 2) = static_cast<float>(n.z());
161
162 mat(0, 3) = static_cast<float>(m_corner00.x());
163 mat(1, 3) = static_cast<float>(m_corner00.y());
164 mat(2, 3) = static_cast<float>(m_corner00.z());
165
166 return mat;
167}
168
169//=============================================================================================================
170
171void SliceObject::setWindowLevel(float center, float width)
172{
173 m_windowCenter = center;
174 m_windowWidth = width;
175}
176
177//=============================================================================================================
178
180{
181 return m_windowCenter;
182}
183
184//=============================================================================================================
185
187{
188 return m_windowWidth;
189}
190
191//=============================================================================================================
192
194{
195 m_opacity = opacity;
196}
197
198//=============================================================================================================
199
201{
202 return m_opacity;
203}
204
205//=============================================================================================================
206
207void SliceObject::generateQuadVertices(QVector<float>& vertices) const
208{
209 // 4 vertices: pos(3) + uv(2) = 5 floats each → 20 floats total
210 vertices.resize(20);
211 float* p = vertices.data();
212
213 // Vertex 0: corner00, uv(0,0)
214 *p++ = static_cast<float>(m_corner00.x());
215 *p++ = static_cast<float>(m_corner00.y());
216 *p++ = static_cast<float>(m_corner00.z());
217 *p++ = 0.0f; *p++ = 0.0f;
218
219 // Vertex 1: corner10, uv(1,0)
220 *p++ = static_cast<float>(m_corner10.x());
221 *p++ = static_cast<float>(m_corner10.y());
222 *p++ = static_cast<float>(m_corner10.z());
223 *p++ = 1.0f; *p++ = 0.0f;
224
225 // Vertex 2: corner01, uv(0,1)
226 *p++ = static_cast<float>(m_corner01.x());
227 *p++ = static_cast<float>(m_corner01.y());
228 *p++ = static_cast<float>(m_corner01.z());
229 *p++ = 0.0f; *p++ = 1.0f;
230
231 // Vertex 3: corner11, uv(1,1)
232 *p++ = static_cast<float>(m_corner11.x());
233 *p++ = static_cast<float>(m_corner11.y());
234 *p++ = static_cast<float>(m_corner11.z());
235 *p++ = 1.0f; *p++ = 1.0f;
236}
237
238//=============================================================================================================
239
240void SliceObject::generateQuadIndices(QVector<unsigned int>& indices)
241{
242 // Two triangles: (0,1,2) and (2,1,3)
243 indices = { 0, 1, 2, 2, 1, 3 };
244}
SliceObject class declaration — MRI volume slice renderable.
3-D brain visualisation using the Qt RHI rendering backend.
SliceOrientation
Orientation for an orthogonal MRI slice.
Definition sliceobject.h:70
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 generateQuadVertices(QVector< float > &vertices) const
SliceOrientation orientation() const
void setOpacity(float opacity)