46#include <QCoreApplication>
47#include <QtConcurrent>
50#define _USE_MATH_DEFINES
54#include <Eigen/Sparse>
84static std::optional<FiffCoordTrans> make_voxel_ras_trans(
const Eigen::Vector3f& r0,
85 const Eigen::Vector3f& x_ras,
86 const Eigen::Vector3f& y_ras,
87 const Eigen::Vector3f& z_ras,
88 const Eigen::Vector3f& voxel_size)
91 rot.row(0) = x_ras.transpose() * voxel_size[0];
92 rot.row(1) = y_ras.transpose() * voxel_size[1];
93 rot.row(2) = z_ras.transpose() * voxel_size[2];
112 curv = Eigen::VectorXf::Ones(
np);
140 Eigen::VectorXi result(
static_cast<int>(
nearest.size()));
141 for (
int i = 0; i < result.size(); ++i)
150 Eigen::VectorXd result(
static_cast<int>(
nearest.size()));
151 for (
int i = 0; i < result.size(); ++i)
160 const int n = nearestIdx.size();
162 for (
int i = 0; i < n; ++i) {
164 nearest[i].nearest = nearestIdx[i];
165 nearest[i].dist =
static_cast<float>(nearestDist[i]);
178 Eigen::Vector3d v1 = (tri.
r1 - from).cast<double>();
179 Eigen::Vector3d v2 = (tri.
r2 - from).cast<double>();
180 Eigen::Vector3d v3 = (tri.
r3 - from).cast<double>();
182 double triple = v1.cross(v2).dot(v3);
184 double l1 = v1.norm();
185 double l2 = v2.norm();
186 double l3 = v3.norm();
187 double s = (l1*l2*l3+v1.dot(v2)*l3+v1.dot(v3)*l2+v2.dot(v3)*l1);
189 return (2.0*atan2(triple,s));
213 for (k = 0, tri =
tris.data(); k <
ntri; k++, tri++) {
215 tri->
r1 =
rr.row(tri->
vert[0]).transpose();
216 tri->
r2 =
rr.row(tri->
vert[1]).transpose();
217 tri->
r3 =
rr.row(tri->
vert[2]).transpose();
221#ifdef TRIANGLE_SIZE_WARNING
222 for (k = 0, tri =
tris.data(); k <
ntri; k++, tri++)
224 qWarning(
"Warning: Triangle area is only %g um^2 (%.5f %% of expected average)\n",
229 qInfo(
"\ttotal area = %-.1f cm^2\n",1e4*
tot_area);
238 tri->
r1 =
rr.row(tri->
vert[0]).transpose();
239 tri->
r2 =
rr.row(tri->
vert[1]).transpose();
240 tri->
r3 =
rr.row(tri->
vert[2]).transpose();
255 cm[0] =
cm[1] =
cm[2] = 0.0;
256 for (q = 0; q <
np; q++) {
292 qInfo(
"\tDistances between neighboring vertices...");
293 for (k = 0, ndist = 0; k <
np; k++) {
297 for (p = 0; p < nneigh; p++) {
306 qInfo(
"[%d distances done]\n",ndist);
324 nn = MNESurfaceOrVolume::NormalsT::Zero(
np,3);
329 for (p = 0, tri =
tris.data(); p <
ntri; p++, tri++) {
335 for (k = 0; k < 3; k++)
336 for (c = 0; c < 3; c++)
337 nn(ii[k],c) += w*tri->
nn[c];
339 for (k = 0; k <
np; k++) {
340 size =
nn.row(k).norm();
361 int nfix_distinct,nfix_no_neighbors,nfix_defect;
374 nn = MNESurfaceOrVolume::NormalsT::Zero(
np,3);
385 for (p = 0, tri =
tris.data(); p <
ntri; p++, tri++)
387 qWarning(
"\tWarning : zero size triangle # %d\n",p);
388 qInfo(
"\tTriangle ");
390 qInfo(
"and vertex ");
391 qInfo(
"normals and neighboring triangles...");
392 for (p = 0, tri =
tris.data(); p <
ntri; p++, tri++) {
395 for (k = 0; k < 3; k++) {
400 for (c = 0; c < 3; c++)
401 nn(ii[k],c) += w*tri->
nn[c];
410 nfix_no_neighbors = 0;
412 for (k = 0; k <
np; k++) {
415 err_printf_set_error(
"Vertex %d does not have any neighboring triangles!",k);
418#ifdef REPORT_WARNINGS
419 qWarning(
"Warning: Vertex %d does not have any neighboring triangles!\n",k);
425#ifdef REPORT_WARNINGS
426 qWarning(
"\n\tTopological defect: Vertex %d has only %d neighboring triangle%s Vertex omitted.\n\t",
437 for (k = 0; k <
np; k++)
439 size =
nn.row(k).norm();
447 qInfo(
"\tVertex neighbors...");
454 for (k = 0; k <
np; k++) {
464 for (k = 0; k <
np; k++) {
471 for (c = 0; c < 3; c++) {
474 for (q = 0, found =
false; q < nneighbors; q++) {
475 if (neighbors[q] == vert) {
482 neighbors[nneighbors++] = vert;
484 if (check_too_many_neighbors) {
485 qCritical(
"Too many neighbors for vertex %d.",k);
489 qWarning(
"\tWarning: Too many neighbors for vertex %d\n",k);
496#ifdef REPORT_WARNINGS
497 qWarning(
"\n\tIncorrect number of distinct neighbors for vertex %d (%d instead of %d) [fixed].",
514 qWarning(
"\tWarning: %d topological defects were fixed.\n",nfix_defect);
515 if (nfix_distinct > 0)
516 qWarning(
"\tWarning: %d vertices had incorrect number of distinct neighbors (fixed).\n",nfix_distinct);
517 if (nfix_no_neighbors > 0)
518 qWarning(
"\tWarning: %d vertices did not have any neighboring triangles (fixed)\n",nfix_no_neighbors);
520 for (k = 0; k <
np; k++) {
522 qCritical(
"No neighbors for vertex %d\n",k);
524 qCritical(
"No neighbor tris for vertex %d\n",k);
Header-only Eigen matrix text I/O — round-trips dense matrices to whitespace-separated ASCII for cros...
Discriminated geometry container that can represent either a triangulated surface or a discrete/volum...
FreeSurfer volume geometry header carried by surface and tag streams.
Ordered group of MNELIB::MNEMghTag entries appended to an MGH/MGZ file.
Lightweight triangulated surface (vertices, triangles, normals) used by surface-based routines.
Single-hemisphere source space (cortical surface or volume grid) loaded from FIFF.
#define MNE_SOURCE_SPACE_SURFACE
#define MNE_SOURCE_SPACE_VOLUME
Patch information (cluster of cortex vertices around each decimated source) used by orientation prior...
Legacy MNE-C aggregator for SSP projections plus the channel list they apply to.
Triangle descriptor with cached centroid, area and normal vectors.
Argument record passed to a background raw-data filter worker.
One renderable surface (cortex / pial / inflated / BEM) inside an MSH display set.
Per-source-space-vertex nearest-cortex-vertex mapping.
Single FreeSurfer MGH/MGZ tag (key, length, opaque payload).
return FiffCoordTrans(from_frame, to_frame, R, moveVec)
#define FIFFV_MNE_COORD_MRI_VOXEL
High-level digitization data: dig points plus the device→head transform and fitting metadata that tog...
4x4 affine FIFF coordinate transform (FIFF_COORD_TRANS) annotated with source/destination coordinate-...
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
Single digitization point (FIFF_DIG_POINT) with kind (cardinal/HPI/EEG/extra), identifier and 3D coor...
Best-fit sphere from a 3-D point cloud with closed-form and Nelder–Mead solvers.
Core MNE data structures (source spaces, source estimates, hemispheres).
FIFF file I/O, in-memory data structures and high-level readers/writers.
std::vector< Eigen::VectorXi > neighbor_tri
void setNearestData(const Eigen::VectorXi &nearestIdx, const Eigen::VectorXd &nearestDist)
std::vector< Eigen::VectorXi > neighbor_vert
MNESurfaceOrVolume()
Constructs the MNE FsSurface or Volume.
Eigen::VectorXd nearestDistVec() const
int add_geometry_info(bool do_normals, bool check_too_many_neighbors)
FIFFLIB::FiffSparseMatrix dist
std::vector< MNENearest > nearest
Eigen::VectorXi nneighbor_vert
Eigen::VectorXi nneighbor_tri
void calculate_vertex_distances()
static void compute_cm(const PointsT &rr, int np, float(&cm)[3])
static double solid_angle(const Eigen::Vector3f &from, const MNELIB::MNETriangle &tri)
void compute_surface_cm()
virtual ~MNESurfaceOrVolume()
Destroys the MNE FsSurface or Volume description.
std::vector< MNETriangle > tris
std::vector< Eigen::VectorXf > vert_dist
Eigen::Matrix< float, Eigen::Dynamic, 3, Eigen::RowMajor > PointsT
int add_geometry_info2(bool do_normals)
Eigen::VectorXi nearestVertIdx() const
std::vector< MNETriangle > use_tris
Per-triangle geometric data for a cortical or BEM surface.