v2.0.0
Loading...
Searching...
No Matches
mne_msh_display_surface_set.cpp
Go to the documentation of this file.
1//=============================================================================================================
35
36//=============================================================================================================
37// INCLUDES
38//=============================================================================================================
39
41
43#include "mne_surface.h"
44#include "mne_surface_patch.h"
45#include "mne_source_space.h"
46#include "mne_msh_light_set.h"
47#include "mne_msh_light.h"
48#include "mne_msh_eyes.h"
49
50//=============================================================================================================
51// EIGEN INCLUDES
52//=============================================================================================================
53
54#include <Eigen/Core>
55
56//=============================================================================================================
57// QT INCLUDES
58//=============================================================================================================
59
60#include <qmath.h>
61#include <QDebug>
62
63//=============================================================================================================
64// CONSTANTS
65//=============================================================================================================
66
67namespace {
68
69constexpr int SURF_LEFT_HEMI = FIFFV_MNE_SURF_LEFT_HEMI;
70constexpr int SURF_RIGHT_HEMI = FIFFV_MNE_SURF_RIGHT_HEMI;
71constexpr int SURF_LEFT_MORPH_HEMI = (1 << 16 | FIFFV_MNE_SURF_LEFT_HEMI);
72constexpr int SURF_RIGHT_MORPH_HEMI = (1 << 16 | FIFFV_MNE_SURF_RIGHT_HEMI);
73
74constexpr int SHOW_CURVATURE_NONE = 0;
75constexpr int SHOW_CURVATURE_OVERLAY = 1;
76constexpr int SHOW_OVERLAY_HEAT = 1;
77
78constexpr float POS_CURV_COLOR = 0.25f;
79constexpr float NEG_CURV_COLOR = 0.375f;
80constexpr float EVEN_CURV_COLOR = 0.375f;
81
82} // anonymous namespace
83
84//=============================================================================================================
85// STATIC DATA
86//=============================================================================================================
87
88static MNELIB::MNEMshEyes default_eyes;
89static MNELIB::MNEMshEyes* all_eyes = nullptr;
90static int neyes = 0;
91static int current_eyes = -1;
92
93static std::unique_ptr<MNELIB::MNEMshLightSet> custom_lights;
94
95//=============================================================================================================
96// USED NAMESPACES
97//=============================================================================================================
98
99using namespace MNELIB;
100
101//=============================================================================================================
102// DEFINE MEMBER METHODS
103//=============================================================================================================
104
106{
107 Eigen::Map<Eigen::Vector3f>(default_eyes.left) = Eigen::Vector3f(-0.2f, 0.0f, 0.0f);
108 Eigen::Map<Eigen::Vector3f>(default_eyes.right) = Eigen::Vector3f( 0.2f, 0.0f, 0.0f);
109 Eigen::Map<Eigen::Vector3f>(default_eyes.left_up) = Eigen::Vector3f(0.0f, 0.0f, 1.0f);
110 Eigen::Map<Eigen::Vector3f>(default_eyes.right_up) = Eigen::Vector3f(0.0f, 0.0f, 1.0f);
111
112 this->nsurf = nsurf;
113 if (nsurf > 0) {
114 surfs.resize(nsurf);
115 patches.resize(nsurf);
116 patch_rot.resize(nsurf, 0.0f);
117 active = Eigen::VectorXi::Zero(nsurf);
118 drawable = Eigen::VectorXi::Ones(nsurf);
119 }
120
121 use_patches = false;
122
123 Eigen::Vector3f::Map(rot) = Eigen::Vector3f::Zero();
124 Eigen::Vector3f::Map(move) = Eigen::Vector3f::Zero();
125 Eigen::Vector3f::Map(eye) = Eigen::Vector3f(1.0f, 0.0f, 0.0f);
126 Eigen::Vector3f::Map(up) = Eigen::Vector3f(0.0f, 0.0f, 1.0f);
127
128 Eigen::Vector3f::Map(bg_color) = Eigen::Vector3f::Zero();
129 Eigen::Vector3f::Map(text_color) = Eigen::Vector3f::Ones();
130}
131
132//=============================================================================================================
133
135
136//=============================================================================================================
137
138std::unique_ptr<MNEMshDisplaySurfaceSet> MNEMshDisplaySurfaceSet::load(const QString &subject_id, const QString &surf, const QString &subjects_dir)
139 /*
140 * Load new display surface data
141 */
142{
143 QString pathLh = QString("%1/%2/surf/%3.%4").arg(subjects_dir).arg(subject_id).arg("lh").arg(surf);
144 QString pathLhCurv = QString("%1/%2/surf/%3.%4").arg(subjects_dir).arg(subject_id).arg("lh").arg("curv");
145 QString pathRh = QString("%1/%2/surf/%3.%4").arg(subjects_dir).arg(subject_id).arg("rh").arg(surf);
146 QString pathRhCurv = QString("%1/%2/surf/%3.%4").arg(subjects_dir).arg(subject_id).arg("rh").arg("curv");
147
148 qInfo("Loading surface %s ...\n", pathLh.toUtf8().constData());
149 auto left = MNESourceSpace::load_surface(pathLh, pathLhCurv);
150 if (!left) {
151 left = MNESourceSpace::load_surface(pathLh, QString());
152 if (!left)
153 return nullptr;
154 left->add_uniform_curv();
155 }
156
157 qInfo("Loading surface %s ...\n", pathRh.toUtf8().constData());
158 auto right = MNESourceSpace::load_surface(pathRh, pathRhCurv);
159 if (!right) {
160 right = MNESourceSpace::load_surface(pathRh, QString());
161 if (!right)
162 return nullptr;
163 right->add_uniform_curv();
164 }
165
166 auto result = std::make_unique<MNEMshDisplaySurfaceSet>(2);
167
168 result->surfs[0] = std::make_unique<MNEMshDisplaySurface>();
169 result->surfs[1] = std::make_unique<MNEMshDisplaySurface>();
170
171 result->active[0] = true;
172 result->active[1] = false;
173 result->drawable[0] = true;
174 result->drawable[1] = true;
175
176 auto* pThis = result->surfs[0].get();
177 pThis->filename = pathLh;
178 static_cast<MNESurfaceOrVolume&>(*pThis) = std::move(static_cast<MNESurfaceOrVolume&>(*left));
179 pThis->id = SURF_LEFT_HEMI;
180 pThis->subj = subject_id;
181 pThis->surf_name = surf;
182
183 pThis->decide_surface_extent("Left hemisphere");
184 pThis->decide_curv_display(surf);
185 pThis->setup_curvature_colors();
186
187 pThis = result->surfs[1].get();
188 pThis->filename = pathRh;
189 static_cast<MNESurfaceOrVolume&>(*pThis) = std::move(static_cast<MNESurfaceOrVolume&>(*right));
190 pThis->id = SURF_RIGHT_HEMI;
191 pThis->subj = subject_id;
192 pThis->surf_name = surf;
193
194 pThis->decide_surface_extent("Right hemisphere");
195 pThis->decide_curv_display(surf);
196 pThis->setup_curvature_colors();
197
198 result->apply_left_right_eyes();
199 result->setup_current_lights();
200
201 return result;
202}
203
204//=============================================================================================================
205
207 int kind,
208 const QString& bemname,
209 int full_geom,
210 int check)
211{
212 qInfo("Loading BEM surface %s (id = %d) from %s ...\n",
213 bemname.toUtf8().constData(), kind, filepath.toUtf8().constData());
214
215 std::unique_ptr<MNESurface> surf(MNESurface::read_bem_surface2(filepath,kind,full_geom));
216 if (!surf)
217 return -1;
218
219 if (check) {
220 surf->compute_surface_cm();
221 double sum = surf->sum_solids(Eigen::Map<const Eigen::Vector3f>(surf->cm)) / (4*M_PI);
222 if (std::fabs(sum - 1.0) > 1e-4) {
223 qCritical( "%s surface is not closed "
224 "(sum of solid angles = %g * 4*PI).",
225 bemname.toUtf8().constData(), sum);
226 return -1;
227 }
228 }
229
230 auto newSurf = std::make_unique<MNEMshDisplaySurface>();
231 newSurf->filename = filepath;
232 //newSurf->time_loaded = time(nullptr); //Comment out due to unknown timestamp function ToDo
233 static_cast<MNESurfaceOrVolume&>(*newSurf) = std::move(static_cast<MNESurfaceOrVolume&>(*surf));
234 newSurf->id = kind;
235 newSurf->surf_name = bemname;
236
237 newSurf->curvature_color_mode = SHOW_CURVATURE_NONE;
238 newSurf->overlay_color_mode = SHOW_OVERLAY_HEAT;
239
240 newSurf->decide_surface_extent(bemname);
241 add_replace_surface(std::move(newSurf), true, true);
244
245 return 0;
246}
247
248//=============================================================================================================
249
250void MNEMshDisplaySurfaceSet::add_replace_surface(std::unique_ptr<MNEMshDisplaySurface> newSurf,
251 bool replace,
252 bool drawable)
253{
254 if (replace) {
255 for (int k = 0; k < nsurf; k++) {
256 auto& surf = surfs[k];
257 if (surf->id == newSurf->id) {
258 newSurf->transparent = surf->transparent;
259 newSurf->show_aux_data = surf->show_aux_data;
260 surfs[k] = std::move(newSurf);
261 if (!drawable) {
262 active[k] = false;
263 this->drawable[k] = false;
264 }
265 return;
266 }
267 }
268 }
269 if (newSurf) { /* New surface */
270 surfs.push_back(std::move(newSurf));
271 patches.push_back(nullptr);
272 patch_rot.push_back(0.0f);
273 active.conservativeResize(nsurf+1);
274 this->drawable.conservativeResize(nsurf+1);
276 this->drawable[nsurf] = drawable;
277 nsurf++;
278 }
279}
280
281//=============================================================================================================
282
284{
285 MNEMshEyes* eyes = nullptr;
286
287 if (neyes == 0 || current_eyes < 0 || current_eyes > neyes-1) {
288 eyes = &default_eyes;
289 } else {
290 eyes = all_eyes+current_eyes;
291 }
292
293 for (int k = 0; k < nsurf; k++) {
294 auto* surf = surfs[k].get();
295 switch(surf->id) {
296 case SURF_LEFT_HEMI :
297 case SURF_LEFT_MORPH_HEMI :
298 surf->eye = Eigen::Vector3f::Map(eyes->left);
299 surf->up = Eigen::Vector3f::Map(eyes->left_up);
300 break;
301 case SURF_RIGHT_HEMI :
302 case SURF_RIGHT_MORPH_HEMI :
303 surf->eye = Eigen::Vector3f::Map(eyes->right);
304 surf->up = Eigen::Vector3f::Map(eyes->right_up);
305 break;
306 default :
307 surf->eye = Eigen::Vector3f::Map(eyes->left);
308 surf->up = Eigen::Vector3f::Map(eyes->left_up);
309 break;
310 }
311 }
312}
313
314//=============================================================================================================
315
317{
318 for (int k = 0; k < nsurf; k++) {
319 if (neyes == 0 || current_eyes < 0 || current_eyes > neyes-1) {
320 surfs[k]->eye = Eigen::Vector3f::Map(default_eyes.left);
321 surfs[k]->up = Eigen::Vector3f::Map(default_eyes.left_up);
322 }
323 else {
324 surfs[k]->eye = Eigen::Vector3f::Map(all_eyes[current_eyes].left);
325 surfs[k]->up = Eigen::Vector3f::Map(all_eyes[current_eyes].left_up);
326 }
327 }
328}
329
330//=============================================================================================================
331
337
338//=============================================================================================================
339
341{
342 if (!custom_lights) {
343 custom_lights = std::make_unique<MNEMshLightSet>();
344
345 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, 0.0f, 0.0f, 1.0f, 0.8f, 0.8f, 0.8f));
346 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, 0.0f, 0.0f, -1.0f, 0.8f, 0.8f, 0.8f));
347 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, 0.6f, -1.0f, -1.0f, 0.6f, 0.6f, 0.6f));
348 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, -0.6f, -1.0f, -1.0f, 0.6f, 0.6f, 0.6f));
349 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, 1.0f, 0.0f, 0.0f, 0.8f, 0.8f, 0.8f));
350 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, -1.0f, 0.0f, 0.0f, 0.8f, 0.8f, 0.8f));
351 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(true, 0.0f, 1.0f, 0.5f, 0.6f, 0.6f, 0.6f));
352 custom_lights->lights.push_back(std::make_unique<MNEMshLight>(false, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 1.0f));
353 }
354}
355
356//=============================================================================================================
357
358std::unique_ptr<MNEMshLightSet> MNEMshDisplaySurfaceSet::dup_light_set(const MNEMshLightSet& s)
359{
360 auto res = std::make_unique<MNEMshLightSet>();
361
362 for (const auto &light : s.lights)
363 res->lights.push_back(std::make_unique<MNEMshLight>(*light));
364
365 return res;
366}
367
368//=============================================================================================================
369
374
#define M_PI
#define FIFFV_MNE_SURF_RIGHT_HEMI
#define FIFFV_MNE_SURF_LEFT_HEMI
MNEMshEyes class declaration.
MNEMshDisplaySurfaceSet class declaration.
MNESourceSpace class declaration.
constexpr float NEG_CURV_COLOR
constexpr int SHOW_CURVATURE_OVERLAY
constexpr float POS_CURV_COLOR
constexpr int SHOW_CURVATURE_NONE
constexpr int SHOW_OVERLAY_HEAT
constexpr float EVEN_CURV_COLOR
MNEMshLightSet class declaration.
MNEMshDisplaySurface class declaration.
MNESurfacePatch class declaration.
MNEMshLight class declaration.
MNESurface class declaration.
Core MNE data structures (source spaces, source estimates, hemispheres).
void setup_lights(const MNEMshLightSet &set)
static std::unique_ptr< MNEMshDisplaySurfaceSet > load(const QString &subject_id, const QString &surf, const QString &subjects_dir)
std::unique_ptr< MNEMshLightSet > lights
static std::unique_ptr< MNEMshLightSet > dup_light_set(const MNEMshLightSet &s)
std::vector< std::unique_ptr< MNEMshDisplaySurface > > surfs
void add_replace_surface(std::unique_ptr< MNEMshDisplaySurface > newSurf, bool replace, bool drawable)
std::vector< std::unique_ptr< MNESurfacePatch > > patches
int add_bem_surface(const QString &filepath, int kind, const QString &bemname, int full_geom, int check)
Eye/camera position and gaze direction for 3-D surface rendering.
Collection of lights defining the lighting setup for 3-D rendering.
std::vector< std::unique_ptr< MNEMshLight > > lights
static std::unique_ptr< MNESourceSpace > load_surface(const QString &surf_file, const QString &curv_file)
static std::unique_ptr< MNESurface > read_bem_surface2(const QString &name, int which, bool add_geometry)
Defines a source space or a surface.