105 qInfo(
"\tCompleting triangulation info...");
107 this->
tri_nn = MatrixX3d::Zero(this->
ntri, 3);
114 for (qint32 i = 0; i < this->
ntri; ++i) {
115 for (qint32 j = 0; j < 3; ++j) {
116 k = this->
itris(i, j);
118 r(j, 0) = this->
rr(k, 0);
119 r(j, 1) = this->
rr(k, 1);
120 r(j, 2) = this->
rr(k, 2);
129 a = (r.row(1) - r.row(0)).transpose();
130 b = (r.row(2) - r.row(0)).transpose();
131 this->
tri_nn(i, 0) = a(1) * b(2) - a(2) * b(1);
132 this->
tri_nn(i, 1) = a(2) * b(0) - a(0) * b(2);
133 this->
tri_nn(i, 2) = a(0) * b(1) - a(1) * b(0);
136 size = this->
tri_nn.row(i) * this->
tri_nn.row(i).transpose();
137 size = std::pow(size, 0.5f);
140 this->
tri_nn.row(i) /= size;
143 qInfo(
"Adding additional geometry info\n");
161 std::vector<std::vector<int>> temp_ntri(this->
np);
162 for (p = 0; p < this->
itris.rows(); p++) {
163 for (k = 0; k < 3; k++) {
164 temp_ntri[this->
itris(p, k)].push_back(p);
168 for (k = 0; k < static_cast<int>(temp_ntri.size()); k++) {
169 neighbor_tri[k] = Eigen::Map<Eigen::VectorXi>(temp_ntri[k].data(), temp_ntri[k].size());
175 std::vector<std::vector<int>> temp_nvert(this->
np);
176 for (k = 0; k < this->
np; k++) {
179 for (c = 0; c < 3; c++) {
185 for (q = 0; q < static_cast<int>(temp_nvert[k].size()); q++) {
186 if (temp_nvert[k][q] == vert) {
193 temp_nvert[k].push_back(vert);
200 for (k = 0; k < this->np; k++) {
201 neighbor_vert[k] = Eigen::Map<Eigen::VectorXi>(temp_nvert[k].data(), temp_nvert[k].size());
271 const QList<int>& targetVertices)
273 QList<MNEBemSurface> results;
275 if (outerSkin.
np <= 0 || outerSkin.
ntri <= 0) {
276 qWarning(
"MNEBemSurface::makeScalpSurfaces - Input surface is empty.");
280 for (
int target : targetVertices) {
281 if (target >= outerSkin.
np) {
292 Eigen::MatrixX3d
rr = surf.
rr.cast<
double>();
293 Eigen::MatrixX3d
nn = surf.
nn.cast<
double>();
296 int nTri = surf.
ntri;
297 std::vector<std::array<int, 3>>
tris(nTri);
298 for (
int i = 0; i < nTri; ++i) {
303 int currentNp = surf.
np;
304 std::vector<bool> vertAlive(currentNp,
true);
306 std::vector<int> redirect(currentNp);
307 for (
int i = 0; i < currentNp; ++i)
310 auto resolve = [&](
int v) ->
int {
311 while (redirect[v] != v)
316 while (currentNp > target) {
318 double bestLen = std::numeric_limits<double>::max();
322 for (
int t = 0; t < static_cast<int>(
tris.size()); ++t) {
323 int v0 = resolve(
tris[t][0]);
324 int v1 = resolve(
tris[t][1]);
325 int v2 = resolve(
tris[t][2]);
327 if (v0 == v1 || v1 == v2 || v0 == v2)
330 double d01 = edgeLenSq(
rr, v0, v1);
331 double d12 = edgeLenSq(
rr, v1, v2);
332 double d20 = edgeLenSq(
rr, v2, v0);
355 int va = resolve(
tris[bestTri][bestEdge]);
356 int vb = resolve(
tris[bestTri][(bestEdge + 1) % 3]);
359 rr.row(va) = (
rr.row(va) +
rr.row(vb)) * 0.5;
360 nn.row(va) = (
nn.row(va) +
nn.row(vb)).normalized();
364 vertAlive[vb] =
false;
369 std::vector<int> oldToNew(surf.
np, -1);
371 for (
int i = 0; i < surf.
np; ++i) {
372 if (vertAlive[i] && resolve(i) == i) {
373 oldToNew[i] = newNp++;
378 decimated.
id = surf.
id;
381 decimated.
np = newNp;
385 Eigen::MatrixX3f newNn(newNp, 3);
386 for (
int i = 0; i < surf.
np; ++i) {
387 if (oldToNew[i] >= 0) {
388 newRr.row(oldToNew[i]) =
rr.row(i).cast<
float>();
389 newNn.row(oldToNew[i]) =
nn.row(i).cast<
float>();
392 decimated.
rr = newRr;
393 decimated.
nn = newNn;
396 std::vector<std::array<int, 3>> newTris;
397 for (
const auto& tri :
tris) {
398 int a = oldToNew[resolve(tri[0])];
399 int b = oldToNew[resolve(tri[1])];
400 int c = oldToNew[resolve(tri[2])];
401 if (a >= 0 && b >= 0 && c >= 0 && a != b && b != c && a != c) {
402 newTris.push_back({a, b, c});
406 decimated.
ntri =
static_cast<int>(newTris.size());
408 for (
int i = 0; i < decimated.
ntri; ++i) {
409 newItris(i, 0) = newTris[i][0];
410 newItris(i, 1) = newTris[i][1];
411 newItris(i, 2) = newTris[i][2];
413 decimated.
itris = newItris;
418 results.append(decimated);