106 qInfo(
"\tCompleting triangulation info...");
108 this->
tri_nn = MatrixX3d::Zero(this->
ntri, 3);
115 for (qint32 i = 0; i < this->
ntri; ++i) {
116 for (qint32 j = 0; j < 3; ++j) {
117 k = this->
itris(i, j);
119 r(j, 0) = this->
rr(k, 0);
120 r(j, 1) = this->
rr(k, 1);
121 r(j, 2) = this->
rr(k, 2);
130 a = (r.row(1) - r.row(0)).transpose();
131 b = (r.row(2) - r.row(0)).transpose();
132 this->
tri_nn(i, 0) = a(1) * b(2) - a(2) * b(1);
133 this->
tri_nn(i, 1) = a(2) * b(0) - a(0) * b(2);
134 this->
tri_nn(i, 2) = a(0) * b(1) - a(1) * b(0);
137 size = this->
tri_nn.row(i) * this->
tri_nn.row(i).transpose();
138 size = std::pow(size, 0.5f);
141 this->
tri_nn.row(i) /= size;
144 std::fstream doc(
"./Output/tri_area.dat", std::ofstream::out | std::ofstream::trunc);
152 qInfo(
"Adding additional geometry info\n");
169 std::vector<std::vector<int>> temp_ntri(this->
itris.rows());
170 for (p = 0; p < this->
itris.rows(); p++) {
171 for (k = 0; k < 3; k++) {
172 temp_ntri[this->
itris(p, k)].push_back(p);
176 for (k = 0; k < static_cast<int>(temp_ntri.size()); k++) {
177 neighbor_tri[k] = Eigen::Map<Eigen::VectorXi>(temp_ntri[k].data(), temp_ntri[k].size());
183 std::vector<std::vector<int>> temp_nvert(this->
np);
184 for (k = 0; k < this->
np; k++) {
187 for (c = 0; c < 3; c++) {
193 for (q = 0; q < static_cast<int>(temp_nvert[k].size()); q++) {
194 if (temp_nvert[k][q] == vert) {
201 temp_nvert[k].push_back(vert);
208 for (k = 0; k < this->np; k++) {
209 neighbor_vert[k] = Eigen::Map<Eigen::VectorXi>(temp_nvert[k].data(), temp_nvert[k].size());
279 const QList<int>& targetVertices)
281 QList<MNEBemSurface> results;
283 if (outerSkin.
np <= 0 || outerSkin.
ntri <= 0) {
284 qWarning(
"MNEBemSurface::makeScalpSurfaces - Input surface is empty.");
288 for (
int target : targetVertices) {
289 if (target >= outerSkin.
np) {
300 Eigen::MatrixX3d
rr = surf.
rr.cast<
double>();
301 Eigen::MatrixX3d
nn = surf.
nn.cast<
double>();
304 int nTri = surf.
ntri;
305 std::vector<std::array<int, 3>>
tris(nTri);
306 for (
int i = 0; i < nTri; ++i) {
311 int currentNp = surf.
np;
312 std::vector<bool> vertAlive(currentNp,
true);
314 std::vector<int> redirect(currentNp);
315 for (
int i = 0; i < currentNp; ++i)
318 auto resolve = [&](
int v) ->
int {
319 while (redirect[v] != v)
324 while (currentNp > target) {
326 double bestLen = std::numeric_limits<double>::max();
330 for (
int t = 0; t < static_cast<int>(
tris.size()); ++t) {
331 int v0 = resolve(
tris[t][0]);
332 int v1 = resolve(
tris[t][1]);
333 int v2 = resolve(
tris[t][2]);
335 if (v0 == v1 || v1 == v2 || v0 == v2)
338 double d01 = edgeLenSq(
rr, v0, v1);
339 double d12 = edgeLenSq(
rr, v1, v2);
340 double d20 = edgeLenSq(
rr, v2, v0);
363 int va = resolve(
tris[bestTri][bestEdge]);
364 int vb = resolve(
tris[bestTri][(bestEdge + 1) % 3]);
367 rr.row(va) = (
rr.row(va) +
rr.row(vb)) * 0.5;
368 nn.row(va) = (
nn.row(va) +
nn.row(vb)).normalized();
372 vertAlive[vb] =
false;
377 std::vector<int> oldToNew(surf.
np, -1);
379 for (
int i = 0; i < surf.
np; ++i) {
380 if (vertAlive[i] && resolve(i) == i) {
381 oldToNew[i] = newNp++;
386 decimated.
id = surf.
id;
389 decimated.
np = newNp;
393 Eigen::MatrixX3f newNn(newNp, 3);
394 for (
int i = 0; i < surf.
np; ++i) {
395 if (oldToNew[i] >= 0) {
396 newRr.row(oldToNew[i]) =
rr.row(i).cast<
float>();
397 newNn.row(oldToNew[i]) =
nn.row(i).cast<
float>();
400 decimated.
rr = newRr;
401 decimated.
nn = newNn;
404 std::vector<std::array<int, 3>> newTris;
405 for (
const auto& tri :
tris) {
406 int a = oldToNew[resolve(tri[0])];
407 int b = oldToNew[resolve(tri[1])];
408 int c = oldToNew[resolve(tri[2])];
409 if (a >= 0 && b >= 0 && c >= 0 && a != b && b != c && a != c) {
410 newTris.push_back({a, b, c});
414 decimated.
ntri =
static_cast<int>(newTris.size());
416 for (
int i = 0; i < decimated.
ntri; ++i) {
417 newItris(i, 0) = newTris[i][0];
418 newItris(i, 1) = newTris[i][1];
419 newItris(i, 2) = newTris[i][2];
421 decimated.
itris = newItris;
426 results.append(decimated);