71 const std::vector<VectorXi> &vecNeighborVertices,
72 VectorXi &vecVertSubset,
76 qint32 iCols =
static_cast<qint32
>(vecVertSubset.size());
77 if(vecVertSubset.size() == 0) {
78 qDebug() <<
"[WARNING] SCDC received empty subset, calculating full distance table, make sure you have enough memory !";
79 vecVertSubset = VectorXi::LinSpaced(matVertices.rows(), 0,
static_cast<int>(matVertices.rows()) - 1);
80 iCols =
static_cast<qint32
>(matVertices.rows());
83 QSharedPointer<MatrixXd> returnMat = QSharedPointer<MatrixXd>::create(matVertices.rows(), iCols);
86 int iCores = QThread::idealThreadCount();
91 qint32 iSubArraySize = int(
double(vecVertSubset.size()) /
double(iCores));
92 QVector<QFuture<void> > vecThreads(iCores);
94 qint32 iEnd = iSubArraySize;
96 for (
int i = 0; i < vecThreads.size(); ++i) {
97 if(i == vecThreads.size()-1)
101 std::cref(matVertices),
102 std::cref(vecNeighborVertices),
103 std::cref(vecVertSubset),
105 static_cast<qint32
>(vecVertSubset.size()),
113 std::cref(matVertices),
114 std::cref(vecNeighborVertices),
115 std::cref(vecVertSubset),
119 iBegin += iSubArraySize;
120 iEnd += iSubArraySize;
124 for (QFuture<void>& f : vecThreads) {
134 const MatrixX3f &matSensorPositions)
136 const qint32 iNumSensors =
static_cast<qint32
>(matSensorPositions.rows());
138 qint32 iCores = QThread::idealThreadCount();
144 const qint32 iSubArraySize = int(
double(iNumSensors) /
double(iCores));
146 if(iSubArraySize <= 1)
148 return nearestNeighbor(matVertices, matSensorPositions, 0, iNumSensors);
151 QVector<QFuture<VectorXi> > vecThreads(iCores);
152 qint32 iBeginOffset = 0;
153 qint32 iEndOffset = iBeginOffset + iSubArraySize;
154 for(qint32 i = 0; i < vecThreads.size(); ++i)
156 if(i == vecThreads.size()-1)
172 iBeginOffset = iEndOffset;
173 iEndOffset += iSubArraySize;
177 for (QFuture<VectorXi>& f : vecThreads) {
182 VectorXi vecOutputArray(iNumSensors);
184 for(qint32 i = 0; i < vecThreads.size(); ++i)
186 const VectorXi& partial = vecThreads[i].result();
187 vecOutputArray.segment(iOffset, partial.size()) = partial;
188 iOffset +=
static_cast<qint32
>(partial.size());
191 return vecOutputArray;
197 const MatrixX3f &matSensorPositions,
201 VectorXi vecMappedSensors(iEnd - iBegin);
203 for(qint32 s = iBegin; s < iEnd; ++s)
205 qint32 iChampionId = 0;
206 double iChampDist = std::numeric_limits<double>::max();
207 for(qint32 i = 0; i < matVertices.rows(); ++i)
209 double dDist = sqrt(
squared(matVertices(i, 0) - matSensorPositions(s, 0))
210 +
squared(matVertices(i, 1) - matSensorPositions(s, 1))
211 +
squared(matVertices(i, 2) - matSensorPositions(s, 2)));
212 if(dDist < iChampDist)
218 vecMappedSensors[s - iBegin] = iChampionId;
221 return vecMappedSensors;
227 const MatrixX3f &matVertices,
228 const std::vector<VectorXi> &vecNeighborVertices,
229 const VectorXi &vecVertSubset,
232 double dCancelDistance) {
233 const std::vector<VectorXi> &vecAdjacency = vecNeighborVertices;
234 qint32 n =
static_cast<qint32
>(vecAdjacency.size());
235 QVector<double> vecMinDists(n);
236 std::set< std::pair< double, qint32> > vertexQ;
239 for (qint32 i = iBegin; i < iEnd; ++i) {
240 if ((i - iBegin) > 0 && (i - iBegin) % 100 == 0) {
241 qDebug() <<
"GeometryInfo::iterativeDijkstra progress:" << (i - iBegin) <<
"/" << (iEnd - iBegin) <<
" (Thread range:" << iBegin <<
"-" << iEnd <<
")";
244 qint32 iRoot = vecVertSubset[i];
246 vecMinDists.fill(INF);
247 vecMinDists[iRoot] = 0.0;
248 vertexQ.insert(std::make_pair(vecMinDists[iRoot], iRoot));
250 while (vertexQ.empty() ==
false) {
251 const double dDist = vertexQ.begin()->first;
252 const qint32 u = vertexQ.begin()->second;
253 vertexQ.erase(vertexQ.begin());
255 if (dDist <= dCancelDistance) {
256 const VectorXi& vecNeighbours = vecAdjacency[u];
258 for (Eigen::Index ne = 0; ne < vecNeighbours.size(); ++ne) {
259 qint32 v = vecNeighbours[ne];
261 const double dDistX = matVertices(u, 0) - matVertices(v, 0);
262 const double dDistY = matVertices(u, 1) - matVertices(v, 1);
263 const double dDistZ = matVertices(u, 2) - matVertices(v, 2);
264 const double dDistWithU = dDist + sqrt(dDistX * dDistX + dDistY * dDistY + dDistZ * dDistZ);
266 if (dDistWithU < vecMinDists[v]) {
267 vertexQ.erase(std::make_pair(vecMinDists[v], v));
268 vecMinDists[v] = dDistWithU;
269 vertexQ.insert(std::make_pair(vecMinDists[v], v));
275 for (qint32 m = 0; m < vecMinDists.size(); ++m) {
276 matOutputDistMatrix->coeffRef(m , i) = vecMinDists[m];
285 qint32 iSensorType) {
286 std::vector<int> vecBadColumns;
287 QVector<const FiffChInfo*> vecSensors;
290 vecSensors.push_back(&s);
294 for(
const QString& b : fiffInfo.
bads){
295 for(
int col = 0; col < vecSensors.size(); ++col){
296 if(vecSensors[col]->ch_name == b){
297 vecBadColumns.push_back(col);
298 for(
int row = 0; row < matDistanceTable->rows(); ++row){
306 return Eigen::Map<VectorXi>(vecBadColumns.data(),
static_cast<Eigen::Index
>(vecBadColumns.size()));
static Eigen::VectorXi filterBadChannels(QSharedPointer< Eigen::MatrixXd > matDistanceTable, const FIFFLIB::FiffInfo &fiffInfo, qint32 iSensorType)
filterBadChannels Filters bad channels from distance table.
static void iterativeDijkstra(QSharedPointer< Eigen::MatrixXd > matOutputDistMatrix, const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, const Eigen::VectorXi &vecVertSubset, qint32 iBegin, qint32 iEnd, double dCancelDistance)
static QSharedPointer< Eigen::MatrixXd > scdc(const Eigen::MatrixX3f &matVertices, const std::vector< Eigen::VectorXi > &vecNeighborVertices, Eigen::VectorXi &vecVertSubset, double dCancelDist=FLOAT_INFINITY)
scdc Calculates surface constrained distances on a mesh.