46#include <QCoreApplication>
47#include <QtConcurrent>
52#ifndef _USE_MATH_DEFINES
53#define _USE_MATH_DEFINES
58#include <Eigen/Sparse>
77[[maybe_unused]]
constexpr int X = 0;
78[[maybe_unused]]
constexpr int Y = 1;
79[[maybe_unused]]
constexpr int Z = 2;
85[[maybe_unused]]
static std::optional<FiffCoordTrans> make_voxel_ras_trans(
const Eigen::Vector3f& r0,
86 const Eigen::Vector3f& x_ras,
87 const Eigen::Vector3f& y_ras,
88 const Eigen::Vector3f& z_ras,
89 const Eigen::Vector3f& voxel_size)
92 rot.row(0) = x_ras.transpose() * voxel_size[0];
93 rot.row(1) = y_ras.transpose() * voxel_size[1];
94 rot.row(2) = z_ras.transpose() * voxel_size[2];
113 curv = Eigen::VectorXf::Ones(
np);
141 Eigen::VectorXi result(
static_cast<int>(
nearest.size()));
142 for (
int i = 0; i < result.size(); ++i)
151 Eigen::VectorXd result(
static_cast<int>(
nearest.size()));
152 for (
int i = 0; i < result.size(); ++i)
161 const int n = nearestIdx.size();
163 for (
int i = 0; i < n; ++i) {
165 nearest[i].nearest = nearestIdx[i];
166 nearest[i].dist =
static_cast<float>(nearestDist[i]);
179 Eigen::Vector3d v1 = (tri.
r1 - from).cast<double>();
180 Eigen::Vector3d v2 = (tri.
r2 - from).cast<double>();
181 Eigen::Vector3d v3 = (tri.
r3 - from).cast<double>();
183 double triple = v1.cross(v2).dot(v3);
185 double l1 = v1.norm();
186 double l2 = v2.norm();
187 double l3 = v3.norm();
188 double s = (l1 * l2 * l3 + v1.dot(v2) * l3 + v1.dot(v3) * l2 + v2.dot(v3) * l1);
190 return (2.0 * atan2(triple, s));
214 for (k = 0, tri =
tris.data(); k <
ntri; k++, tri++) {
216 tri->
r1 =
rr.row(tri->
vert[0]).transpose();
217 tri->
r2 =
rr.row(tri->
vert[1]).transpose();
218 tri->
r3 =
rr.row(tri->
vert[2]).transpose();
222#ifdef TRIANGLE_SIZE_WARNING
223 for (k = 0, tri =
tris.data(); k <
ntri; k++, tri++)
225 qWarning(
"Warning: Triangle area is only %g um^2 (%.5f %% of expected average)\n",
230 qInfo(
"\ttotal area = %-.1f cm^2\n", 1e4 *
tot_area);
239 tri->
r1 =
rr.row(tri->
vert[0]).transpose();
240 tri->
r2 =
rr.row(tri->
vert[1]).transpose();
241 tri->
r3 =
rr.row(tri->
vert[2]).transpose();
256 cm[0] =
cm[1] =
cm[2] = 0.0;
257 for (q = 0; q <
np; q++) {
293 qInfo(
"\tDistances between neighboring vertices...");
294 for (k = 0, ndist = 0; k <
np; k++) {
298 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);
424#ifdef REPORT_WARNINGS
425 qWarning(
"\n\tTopological defect: Vertex %d has only %d neighboring triangle%s Vertex omitted.\n\t",
436 for (k = 0; k <
np; k++)
438 size =
nn.row(k).norm();
446 qInfo(
"\tVertex neighbors...");
453 for (k = 0; k <
np; k++) {
462 for (k = 0; k <
np; k++) {
469 for (c = 0; c < 3; c++) {
472 for (q = 0, found =
false; q < nneighbors; q++) {
473 if (neighbors[q] == vert) {
480 neighbors[nneighbors++] = vert;
482 if (check_too_many_neighbors) {
483 qCritical(
"Too many neighbors for vertex %d.", k);
486 qWarning(
"\tWarning: Too many neighbors for vertex %d\n", k);
493#ifdef REPORT_WARNINGS
494 qWarning(
"\n\tIncorrect number of distinct neighbors for vertex %d (%d instead of %d) [fixed].",
511 qWarning(
"\tWarning: %d topological defects were fixed.\n", nfix_defect);
512 if (nfix_distinct > 0)
513 qWarning(
"\tWarning: %d vertices had incorrect number of distinct neighbors (fixed).\n", nfix_distinct);
514 if (nfix_no_neighbors > 0)
515 qWarning(
"\tWarning: %d vertices did not have any neighboring triangles (fixed)\n", nfix_no_neighbors);
517 for (k = 0; k <
np; k++) {
519 qCritical(
"No neighbors for vertex %d\n", k);
521 qCritical(
"No neighbor tris for vertex %d\n", k);
#define FIFFV_MNE_COORD_MRI_VOXEL
FIFF binary tag-stream layer: wraps a QIODevice to read and write FIFF tags, directories,...
4x4 affine FIFF coordinate transform (FIFF_COORD_TRANS) annotated with source/destination coordinate-...
return FiffCoordTrans(from_frame, to_frame, R, moveVec)
Single digitization point (FIFF_DIG_POINT) with kind (cardinal/HPI/EEG/extra), identifier and 3D coor...
High-level digitization data: dig points plus the device→head transform and fitting metadata that tog...
Header-only Eigen matrix text I/O — round-trips dense matrices to whitespace-separated ASCII for cros...
Best-fit sphere from a 3-D point cloud with closed-form and Nelder–Mead solvers.
One renderable surface (cortex / pial / inflated / BEM) inside an MSH display set.
#define MNE_SOURCE_SPACE_SURFACE
#define MNE_SOURCE_SPACE_VOLUME
Legacy MNE-C aggregator for SSP projections plus the channel list they apply to.
Patch information (cluster of cortex vertices around each decimated source) used by orientation prior...
Triangle descriptor with cached centroid, area and normal vectors.
Lightweight triangulated surface (vertices, triangles, normals) used by surface-based routines.
Single-hemisphere source space (cortical surface or volume grid) loaded from FIFF.
Discriminated geometry container that can represent either a triangulated surface or a discrete/volum...
Single FreeSurfer MGH/MGZ tag (key, length, opaque payload).
FreeSurfer volume geometry header carried by surface and tag streams.
Per-source-space-vertex nearest-cortex-vertex mapping.
Ordered group of MNELIB::MNEMghTag entries appended to an MGH/MGZ file.
Argument record passed to a background raw-data filter worker.
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.