1 #define _USE_MATH_DEFINES
25 void snax::disp()
const
27 cout <<
"snax #" << index <<
"; d " << d <<
"; v " << v <<
"; edgeind " << edgeind <<
"; fromvert " << fromvert
28 <<
"; tovert " << tovert <<
"; isfreeze " << isfreeze <<
"; orderedge " << orderedge <<
" | isBorder "
32 void snaxedge::disp()
const
34 cout <<
"snaxedge #" << index <<
" | surfind " << surfind <<
" "
35 <<
" | isBorder " << isBorder <<
" ";
39 void snaxsurf::disp()
const
41 cout <<
"snaxsurf #" << index << index <<
" | voluind " << voluind <<
" "
42 <<
" | isBorder " << isBorder <<
" ";
47 void snax::write(FILE *fid)
const
49 fprintf(fid,
"%i %lf %lf %i %i %i %i %i \n", index, d, v, edgeind, fromvert, tovert, isfreeze, orderedge);
52 void snaxedge::write(FILE *fid)
const
54 fprintf(fid,
"%i %i %lf %lf %lf \n", index, surfind, normvector(0), normvector(1), normvector(2));
57 void snaxsurf::write(FILE *fid)
const
59 fprintf(fid,
"%i %i %lf %lf %lf \n", index, voluind, normvector(0), normvector(1), normvector(2));
61 void snax::read(FILE *fid)
63 fscanf(fid,
"%i %lf %lf %i %i %i %i %i ", &index, &d, &v, &edgeind, &fromvert, &tovert, &isfreeze, &orderedge);
66 void snaxedge::read(FILE *fid)
68 fscanf(fid,
"%i %i %lf %lf %lf ", &index, &surfind, &normvector[0], &normvector[1], &normvector[2]);
71 void snaxsurf::read(FILE *fid)
73 fscanf(fid,
"%i %i %lf %lf %lf ", &index, &voluind, &normvector[0], &normvector[1], &normvector[2]);
76 void snaxedge::PrepareForUse()
78 normvector.PrepareForUse();
81 void snaxsurf::PrepareForUse()
83 normvector.PrepareForUse();
86 #pragma GCC diagnostic push
87 #pragma GCC diagnostic ignored "-Wunused-parameter"
88 void snax::disptree(
const mesh &meshin,
int n)
const
91 meshin.verts.isearch(index)->disptree(meshin, n);
93 void snaxedge::disptree(
const mesh &meshin,
int n)
const
96 meshin.edges.isearch(index)->disptree(meshin, n);
98 void snaxsurf::disptree(
const mesh &meshin,
int n)
const
101 meshin.surfs.isearch(index)->disptree(meshin, n);
103 void snax::disptree(
const snake &snakein,
int n)
const
106 for (i = 0; i < n; i++)
111 for (i = 0; i < n; i++)
115 snakein.snakeconn.verts.isearch(index)->disp();
118 for (i = 0; unsigned_int(i) < snakein.snakeconn.verts.isearch(index)->edgeind.size(); i++)
120 snakein.snaxedges.isearch(snakein.snakeconn.verts.isearch(index)->edgeind[i])->disptree(snakein, n - 1);
124 void snaxedge::disptree(
const snake &snakein,
int n)
const
127 for (i = 0; i < n; i++)
132 for (i = 0; i < n; i++)
136 snakein.snakeconn.edges.isearch(index)->disp();
139 for (i = 0; unsigned_int(i) < snakein.snakeconn.edges.isearch(index)->vertind.size(); i++)
141 snakein.snaxs.isearch(snakein.snakeconn.edges.isearch(index)->vertind[i])->disptree(snakein, n - 1);
143 for (i = 0; unsigned_int(i) < snakein.snakeconn.edges.isearch(index)->surfind.size(); i++)
145 snakein.snaxsurfs.isearch(snakein.snakeconn.edges.isearch(index)->surfind[i])->disptree(snakein, n - 1);
149 void snaxsurf::disptree(
const snake &snakein,
int n)
const
152 for (i = 0; i < n; i++)
157 for (i = 0; i < n; i++)
161 snakein.snakeconn.surfs.isearch(index)->disp();
164 for (i = 0; unsigned_int(i) < snakein.snakeconn.surfs.isearch(index)->edgeind.size(); i++)
166 snakein.snaxedges.isearch(snakein.snakeconn.surfs.isearch(index)->edgeind[i])->disptree(snakein, n - 1);
171 void snax::ChangeIndices(
int nVert,
int nEdge,
int nSurf,
int nVolu)
175 void snaxedge::ChangeIndices(
int nVert,
int nEdge,
int nSurf,
int nVolu)
179 void snaxsurf::ChangeIndices(
int nVert,
int nEdge,
int nSurf,
int nVolu)
183 void snax::ChangeIndicesSnakeMesh(
int nVert,
int nEdge,
int nSurf,
int nVolu)
189 void snaxedge::ChangeIndicesSnakeMesh(
int nVert,
int nEdge,
int nSurf,
int nVolu)
193 void snaxsurf::ChangeIndicesSnakeMesh(
int nVert,
int nEdge,
int nSurf,
int nVolu)
197 #pragma GCC diagnostic pop
203 bool snaxarray::checkready()
206 this->readyforuse = (this->readyforuse && this->isOrderedOnEdge);
207 return (this->readyforuse);
209 void snaxarray::PrepareForUse()
212 if (isOrderedOnEdge == 0)
214 this->ReorderOnEdge();
218 void snaxarray::Concatenate(
const snaxarray &other)
223 void snaxarray::ForceArrayReady()
233 void snake::disp()
const
239 cout <<
"Snaking Mesh with ";
240 snakemesh()->displight();
242 void snake::displight()
const
244 cout <<
"snake: snax " << snaxs.size();
245 cout <<
"; snaxedges " << snaxedges.size();
246 cout <<
"; snaxsurfs " << snaxsurfs.size() << endl;
248 cout <<
"Snake with connectivity ";
249 snakeconn.displight();
251 cout <<
"Snaking Mesh with ";
252 snakemesh()->displight();
255 void snake::read(FILE *fid)
263 void snake::write(FILE *fid)
const
267 snaxedges.write(fid);
268 snaxsurfs.write(fid);
270 snakeconn.write(fid);
272 int snake::read(
const char *str)
276 fid = fopen(str,
"r");
284 cout <<
"File " << str <<
"Could not be opened to read" << endl;
289 int snake::write(
const char *str)
const
292 fid = fopen(str,
"w");
300 cout <<
"File " << str <<
"Could not be opened to write" << endl;
306 bool snake::isready()
const
308 bool readyforuse =
true;
309 readyforuse = readyforuse & snaxs.isready();
310 readyforuse = readyforuse & snaxedges.isready();
311 readyforuse = readyforuse & snaxsurfs.isready();
312 readyforuse = readyforuse & snakeconn.isready();
313 readyforuse = readyforuse & snakemesh()->isready();
315 return (readyforuse);
318 inline void snake::GetMaxIndex(
int *nVert,
int *nEdge,
int *nSurf,
int *nVolu)
const
320 snakeconn.GetMaxIndex(nVert, nEdge, nSurf, nVolu);
323 void snake::PrepareForUse(
bool needOrder)
325 snaxs.isInMesh =
true;
326 snaxedges.isInMesh =
true;
327 snaxsurfs.isInMesh =
true;
329 snaxs.PrepareForUse();
330 snaxedges.PrepareForUse();
331 snaxsurfs.PrepareForUse();
332 snakeconn.PrepareForUse(needOrder);
333 if (this->snakemesh() != NULL)
335 snakemesh()->PrepareForUse();
340 <<
"Warning: Mesh containing snake unset in snake"
341 " object.\n use `SetSnakeMesh(mesh *snakemeshin)` to set attribute"
342 " `snakemesh` to a mesh pointer"
347 is3D = int(snakemesh()->volus.size()) > 0;
349 if (
int(isMeshVertIn.size()) !=
int(snakemesh()->verts.size()))
351 isMeshVertIn.assign(snakemesh()->verts.size(),
false);
354 void snake::HashArray()
360 snaxedges.HashArray();
361 snaxsurfs.HashArray();
362 snakeconn.HashArray();
363 snakemesh()->HashArray();
365 void snake::HashParent()
371 snaxedges.HashParent();
372 snaxsurfs.HashParent();
374 void snake::HashArrayNM()
380 snaxedges.HashArray();
381 snaxsurfs.HashArray();
382 snakeconn.HashArray();
384 void snake::SetMaxIndex()
390 snaxedges.SetMaxIndex();
391 snaxsurfs.SetMaxIndex();
392 snakeconn.SetMaxIndex();
393 snakemesh()->SetMaxIndex();
395 void snake::SetMaxIndexNM()
401 snaxedges.SetMaxIndex();
402 snaxsurfs.SetMaxIndex();
403 snakeconn.SetMaxIndex();
405 void snake::SetLastIndex()
410 snaxs.SetLastIndex();
411 snaxedges.SetLastIndex();
412 snaxsurfs.SetLastIndex();
413 snakeconn.SetLastIndex();
414 snakemesh()->SetLastIndex();
417 void snake::Init(
mesh *snakemeshin,
int nSnax,
int nEdge,
int nSurf,
int nVolu)
420 is3D = snakemeshin->volus.size() > 0;
423 snaxedges.Init(nEdge);
424 snaxsurfs.Init(nSurf);
426 snaxs.isInMesh =
true;
427 snaxedges.isInMesh =
true;
428 snaxsurfs.isInMesh =
true;
430 snakeconn.Init(nSnax, nEdge, nSurf, nVolu);
432 this->SetSnakeMesh(snakemeshin);
435 void snake::SetSnakeMesh(
mesh *snakemeshin)
437 this->privatesnakemesh = snakemeshin;
438 this->isSetStepLimit =
false;
439 this->isMeshVertIn.assign(snakemeshin->verts.size(),
false);
440 this->edgeStepLimit.assign(this->snakemesh()->edges.size(), 1.0);
442 void snake::reserve(
int nSnax,
int nEdge,
int nSurf,
int nVolu)
446 snaxs.reserve(nSnax);
447 snaxedges.reserve(nEdge);
448 snaxsurfs.reserve(nSurf);
450 snaxs.isInMesh =
true;
451 snaxedges.isInMesh =
true;
452 snaxsurfs.isInMesh =
true;
454 snakeconn.reserve(nSnax, nEdge, nSurf, nVolu);
457 void snake::ChangeIndices(
int nVert,
int nEdge,
int nSurf,
int nVolu)
459 snaxs.ChangeIndices(nVert, nEdge, nSurf, nVolu);
460 snaxedges.ChangeIndices(nVert, nEdge, nSurf, nVolu);
461 snaxsurfs.ChangeIndices(nVert, nEdge, nSurf, nVolu);
462 snakeconn.ChangeIndices(nVert, nEdge, nSurf, nVolu);
464 void snake::ChangeIndicesSnakeMesh(
int nVert,
int nEdge,
int nSurf,
int nVolu)
467 for (ii = 0; ii < snaxs.size(); ++ii)
469 snaxs[ii].ChangeIndicesSnakeMesh(nVert, nEdge, nSurf, nVolu);
471 for (ii = 0; ii < snaxedges.size(); ++ii)
473 snaxedges[ii].ChangeIndicesSnakeMesh(nVert, nEdge, nSurf, nVolu);
475 for (ii = 0; ii < snaxsurfs.size(); ++ii)
477 snaxsurfs[ii].ChangeIndicesSnakeMesh(nVert, nEdge, nSurf, nVolu);
482 snakemesh()->ChangeIndices(nVert, nEdge, nSurf,
486 int CompareSnakeInternalStatus(
const vector<bool> &thisVec,
bool thisFlipped,
const vector<bool> &otherVec,
501 for (ii = 0; ii < ni; ++ii)
503 if ((thisVec[ii] ^ thisFlipped) && (otherVec[ii] ^ otherFlipped))
510 return (
int(isIndep));
512 void snake::Concatenate(
const snake &other,
int isInternal)
521 if (this->snakemesh() == other.snakemesh())
523 this->snaxs.Concatenate(other.snaxs);
524 this->snaxedges.Concatenate(other.snaxedges);
525 this->snaxsurfs.Concatenate(other.snaxsurfs);
526 this->snakeconn.Concatenate(other.snakeconn);
528 ni = isMeshVertIn.size();
532 isIndep = CompareSnakeInternalStatus(isMeshVertIn, ReturnFlip(), other.isMeshVertIn, other.ReturnFlip());
536 isIndep = isInternal <= 0;
542 for (i = 0; i < ni; ++i)
545 ((isMeshVertIn[i] ^ isFlipped) || (other.isMeshVertIn[i] ^ other.isFlipped)) ^ isFlipped;
550 for (i = 0; i < ni; ++i)
553 ((isMeshVertIn[i] ^ isFlipped) && (other.isMeshVertIn[i] ^ other.isFlipped)) ^ isFlipped;
581 void snake::MakeCompatible_inplace(
snake &other)
const
586 int nVert, nEdge, nVolu, nSurf, ii;
589 this->GetMaxIndex(&nVert, &nEdge, &nSurf, &nVolu);
590 other.ChangeIndices(nVert, nEdge, nSurf, nVolu);
591 for (ii = 0; ii < other.snaxs.size(); ++ii)
593 other.snaxs[ii].orderedge = -1;
596 snake snake::MakeCompatible(
snake other)
const
598 MakeCompatible_inplace(other);
602 void snake::VertIsIn(
int vertInd,
bool isIn)
604 if (this->snakemesh() != NULL)
606 int i = this->snakemesh()->verts.find(vertInd);
609 isMeshVertIn[i] = isIn;
613 void snake::VertIsIn(vector<int> vertInd,
bool isIn)
615 if (this->snakemesh() != NULL)
617 int nj = vertInd.size();
618 for (
int j = 0; j < nj; j++)
620 int i = this->snakemesh()->verts.find(vertInd[j]);
623 isMeshVertIn[i] = isIn;
629 void snake::CheckConnectivity()
const
631 int ii, jj, ni, kk, ll, errCount, errTot;
639 ni = int(snaxs.size());
640 for (ii = 0; ii < ni; ++ii)
642 if (snaxs.countparent(snaxs(ii)->KeyParent()) > 1)
644 snaxs.findsiblings(snaxs(ii)->KeyParent(), testSub);
645 for (jj = 0; jj < int(testSub.size()); ++jj)
648 if (snaxedges(ii)->index != snaxedges(testSub[jj])->index)
650 for (kk = 0; kk < int(snakeconn.verts(ii)->edgeind.size()); kk++)
652 if ((snakeconn.edges.isearch(snakeconn.verts(ii)->edgeind[kk])->vertind[0] ==
653 snaxs(testSub[jj])->index) ||
654 (snakeconn.edges.isearch(snakeconn.verts(ii)->edgeind[kk])->vertind[1] ==
655 snaxs(testSub[jj])->index))
665 <<
" Test Snake Connectivity Error :" << errCount <<
" snaxel " << snakeconn.verts(ii)->index
666 <<
" is connected to snaxel " << snaxs(testSub[jj])->index <<
" list: " << endl;
667 snakeconn.verts(ii)->disp();
668 snakeconn.verts(testSub[jj])->disp();
676 cerr <<
"Test Connectivity snax (same edge connectivity) Errors :" << errCount << endl;
680 ni = int(snaxs.size());
683 for (ii = 0; ii < ni; ++ii)
685 if (snakeconn.verts(ii)->edgeind.size() != snakemesh()->edges.isearch(snaxs(ii)->edgeind)->surfind.size())
688 <<
" Test snax number of edges error :" << errCount <<
" snaxel-vertex " << snakeconn.verts(ii)->index
689 <<
" is connected to snaxel " << snaxs(ii)->edgeind <<
" list: " << endl;
690 snakeconn.verts(ii)->disp();
691 snakemesh()->edges.isearch(snaxs(ii)->edgeind)->disp();
697 cerr <<
"Test Connectivity snax (edges in surfs) Errors :" << errCount << endl;
703 ni = int(snaxedges.size());
704 for (ii = 0; ii < ni; ++ii)
706 if (snaxedges.countparent(snaxedges(ii)->KeyParent()) > 1)
708 snaxedges.findsiblings(snaxedges(ii)->KeyParent(), testSub);
709 for (jj = 0; jj < int(testSub.size()); ++jj)
712 if (snaxedges(ii)->index != snaxedges(testSub[jj])->index)
714 for (kk = 0; kk < int(snakeconn.edges(ii)->vertind.size()); kk++)
716 if ((snakeconn.edges(ii)->vertind[kk] == snakeconn.edges(testSub[jj])->vertind[0]) ||
717 (snakeconn.edges(ii)->vertind[kk] == snakeconn.edges(testSub[jj])->vertind[1]))
727 <<
" Test SnakeEdges Connectivity Error :" << errCount <<
" snaxedge "
728 << snakeconn.edges(ii)->index <<
" is connected to snaxedge " << snaxedges(testSub[jj])->index
729 <<
" list: " << endl;
730 snakeconn.edges(ii)->disp();
731 snakeconn.edges(testSub[jj])->disp();
739 cerr <<
"Test Connectivity snaxedge (same surf connectivity) Errors :" << errCount << endl;
745 ni = int(snaxsurfs.size());
746 for (ii = 0; ii < ni; ++ii)
748 if (snaxsurfs.countparent(snaxsurfs(ii)->KeyParent()) > 1)
750 snaxsurfs.findsiblings(snaxsurfs(ii)->KeyParent(), testSub);
751 for (jj = 0; jj < int(testSub.size()); ++jj)
754 if (snaxsurfs(ii)->index != snaxsurfs(testSub[jj])->index)
756 for (kk = 0; kk < int(snakeconn.surfs(ii)->edgeind.size()); kk++)
758 for (ll = 0; ll < int(snakeconn.surfs(testSub[jj])->edgeind.size()); ++ll)
760 if (snakeconn.surfs(testSub[jj])->edgeind[ll] == snakeconn.surfs(ii)->edgeind[kk])
775 <<
" Test SnakeSurf Connectivity Error :" << errCount <<
" snaxsurf "
776 << snakeconn.surfs(ii)->index <<
" is connected to snaxsurf " << snaxsurfs(testSub[jj])->index
777 <<
" list: " << endl;
778 snakeconn.surfs(ii)->disp();
779 snakeconn.surfs(testSub[jj])->disp();
787 cerr <<
"Test Connectivity snaxsurf (same volu connectivity) Errors :" << errCount << endl;
793 cerr << errTot <<
" Total errors were detected in the connectivity list" << endl;
797 void snake::OrderEdges()
801 vector<int> newSurfPairs;
803 newSurfPairs = snakeconn.OrderEdges();
804 nNewSurfs = int(newSurfPairs.size() / 2);
805 for (
int i = 0; i < nNewSurfs; ++i)
807 newSurf = *(snaxsurfs.isearch(newSurfPairs[i * 2]));
808 newSurf.index = newSurfPairs[i * 2 + 1];
809 snaxsurfs.push_back(newSurf);
818 void snake::UpdateDistance(
double dt,
double maxDstep,
bool scaledStep)
822 int nSnax = int(snaxs.size());
824 if (!this->isSetStepLimit && scaledStep)
826 this->SetEdgeStepLimits();
829 for (ii = 0; ii < nSnax; ++ii)
831 double indivMaxDstep = 1.0 * maxDstep;
834 indivMaxDstep = this->SnaxStepLimit(ii) * indivMaxDstep;
836 if (snaxs[ii].v * dt > indivMaxDstep)
838 dStep = indivMaxDstep;
840 else if (snaxs[ii].v * dt < -indivMaxDstep)
842 dStep = -indivMaxDstep;
846 dStep = snaxs[ii].v * dt;
848 snaxs[ii].d = snaxs[ii].d + dStep;
850 snaxs[ii].d = min(max(snaxs[ii].d, 0.0), 1.0);
854 void snake::UpdateDistance(
const vector<double> &dt,
double maxDstep,
bool scaledStep)
858 if (
int(dt.size()) != snaxs.size())
861 "Snake and Dt had mismatched sizes at snake::UpdateDistance",
865 if (!this->isSetStepLimit && scaledStep)
867 this->SetEdgeStepLimits();
870 int nSnax = int(snaxs.size());
871 for (ii = 0; ii < nSnax; ++ii)
873 double indivMaxDstep = 1.0 * maxDstep;
876 indivMaxDstep = this->SnaxStepLimit(ii) * indivMaxDstep;
878 if (snaxs[ii].v * dt[ii] > indivMaxDstep)
880 dStep = indivMaxDstep;
882 else if (snaxs[ii].v * dt[ii] < -indivMaxDstep)
884 dStep = -indivMaxDstep;
888 dStep = snaxs[ii].v * dt[ii];
890 snaxs[ii].d = snaxs[ii].d + dStep;
892 snaxs[ii].d = min(max(snaxs[ii].d, 0.0), 1.0);
904 int nEdges = this->snakemesh()->edges.size();
905 int numParents = this->snakemesh()->meshtree.NumberOfParents();
906 std::vector<int> edgeAccess;
908 edgeAccess.assign(nEdges, 0);
909 this->edgeStepLimit.assign(nEdges, 0.0);
910 edgeInds.reserve(nEdges);
912 for (
int i = 0; i < numParents; ++i)
915 auto parentmesh = this->snakemesh()->meshtree.ParentPointer(i);
918 int nParentVolus = parentmesh->volus.size();
919 for (
int j = 0; j < nParentVolus; ++j)
921 double minEdgeLength = INFINITY;
922 auto snakeMeshVolus = this->snakemesh()->meshtree.ChildIndices(i, parentmesh->volus(j)->index);
924 for (
auto iVolu : snakeMeshVolus)
926 for (
auto iSurf : this->snakemesh()->volus(iVolu)->surfind)
928 for (
auto iEdge : this->snakemesh()->surfs.isearch(iSurf)->edgeind)
930 if (edgeInds.find(iEdge) == rsvs3d::constants::__notfound)
932 minEdgeLength = min(minEdgeLength, this->snakemesh()->edges.isearch(iEdge)->GetLength());
933 edgeInds.push_back(iEdge);
939 for (
auto iEdge : edgeInds.vec)
941 int iEdgePos = this->snakemesh()->edges.find(iEdge);
942 edgeAccess[iEdgePos]++;
943 this->edgeStepLimit[iEdgePos] += minEdgeLength / this->snakemesh()->edges(iEdgePos)->GetLength();
947 for (
int i = 0; i < nEdges; ++i)
949 if (edgeAccess[i] > 1)
951 this->edgeStepLimit[i] = this->edgeStepLimit[i] / double(edgeAccess[i]);
953 else if (edgeAccess[i] < 1)
955 this->edgeStepLimit[i] = 1.0;
960 this->isSetStepLimit =
true;
964 double snake::SnaxStepLimit(
int snaxSub)
const
966 int iEdge = this->snakemesh()->edges.find(this->snaxs(snaxSub)->edgeind);
969 if (iEdge == rsvs3d::constants::__notfound || iEdge >=
int(this->edgeStepLimit.size()))
971 std::cerr << snaxSub <<
"," << this->snaxs.size() <<
"," << this->edgeStepLimit.size() <<
"," << iEdge <<
","
972 << this->snaxs(snaxSub)->edgeind;
973 RSVS3D_ERROR(
"Attemp to access an edge which was not found in "
974 "snake::snakemesh into snake::edgeStepLimit.");
977 return this->edgeStepLimit[iEdge];
980 void snake::UpdateCoord()
982 int fromVertSub, toVertSub;
984 int nSnax = int(snaxs.size());
985 for (ii = 0; ii < nSnax; ++ii)
987 fromVertSub = snakemesh()->verts.find(snaxs(ii)->fromvert);
988 toVertSub = snakemesh()->verts.find(snaxs(ii)->tovert);
990 for (jj = 0; jj < 3; ++jj)
992 snakeconn.verts.elems[ii].coord[jj] =
993 (snakemesh()->verts(toVertSub)->coord[jj] - snakemesh()->verts(fromVertSub)->coord[jj]) * snaxs(ii)->d +
994 snakemesh()->verts(fromVertSub)->coord[jj];
996 for (
auto iEdge : snakeconn.verts(ii)->edgeind)
998 this->snakeconn.InvalidateEdgeLength(iEdge);
1002 this->snakeconn.SetEdgeLengths();
1005 void snake::UpdateCoord(
const vector<int> &snaxInds)
1007 int fromVertSub, toVertSub;
1009 for (
auto iSnax : snaxInds)
1011 ii = this->snaxs.find(iSnax);
1012 fromVertSub = snakemesh()->verts.find(snaxs(ii)->fromvert);
1013 toVertSub = snakemesh()->verts.find(snaxs(ii)->tovert);
1015 for (jj = 0; jj < 3; ++jj)
1017 snakeconn.verts.elems[ii].coord[jj] =
1018 (snakemesh()->verts(toVertSub)->coord[jj] - snakemesh()->verts(fromVertSub)->coord[jj]) * snaxs(ii)->d +
1019 snakemesh()->verts(fromVertSub)->coord[jj];
1021 for (
auto iEdge : snakeconn.verts(ii)->edgeind)
1023 this->snakeconn.InvalidateEdgeLength(iEdge);
1027 this->snakeconn.SetEdgeLengths();
1032 void snaxarray::OrderOnEdge()
1034 vector<int> edgeInds, snaxSubs, orderSubs;
1035 vector<double> orderSnax, unorderSnax;
1036 unordered_multimap<double, int> hashOrder;
1040 edgeInds = ConcatenateScalarField(*
this, &snax::edgeind, 0, elems.size());
1043 for (ii = 0; ii < int(edgeInds.size()); ++ii)
1045 nEdge = hashParent.count(edgeInds[ii]);
1049 snaxSubs = ReturnDataEqualRange(edgeInds[ii], hashParent);
1050 orderSnax.resize(snaxSubs.size());
1051 for (jj = 0; jj < int(snaxSubs.size()); ++jj)
1053 isBwd = elems[snaxSubs[jj]].fromvert > elems[snaxSubs[jj]].tovert;
1054 orderSnax[jj] = isBwd ? (1.0 - elems[snaxSubs[jj]].d) : elems[snaxSubs[jj]].d;
1056 unorderSnax = orderSnax;
1060 orderSubs = FindSubList(orderSnax, unorderSnax, hashOrder);
1061 for (jj = 0; jj < int(snaxSubs.size()); ++jj)
1063 elems[snaxSubs[orderSubs[jj]]].orderedge = jj + 1;
1068 isOrderedOnEdge = 1;
1071 void snaxarray::ReorderOnEdge()
1073 vector<int> edgeInds, snaxSubs;
1074 vector<double> orderSnax;
1076 int ii, jj, nEdge, maxOrd = 0;
1079 edgeInds = ConcatenateScalarField(*
this, &snax::edgeind, 0, elems.size());
1082 for (ii = 0; ii < int(edgeInds.size()); ++ii)
1084 nEdge = hashParent.count(edgeInds[ii]);
1088 snaxSubs = ReturnDataEqualRange(edgeInds[ii], hashParent);
1089 orderSnax.resize(snaxSubs.size());
1090 needIncrement =
false;
1092 for (jj = 0; jj < int(snaxSubs.size()); ++jj)
1094 maxOrd = (maxOrd <= elems[snaxSubs[jj]].orderedge) ? elems[snaxSubs[jj]].orderedge : maxOrd;
1096 for (jj = 0; jj < int(snaxSubs.size()); ++jj)
1098 if (elems[snaxSubs[jj]].orderedge == -1)
1100 isBwd = elems[snaxSubs[jj]].fromvert > elems[snaxSubs[jj]].tovert;
1102 elems[snaxSubs[jj]].orderedge = (isBwd && (elems[snaxSubs[jj]].d == 0.0))
1104 : ((!isBwd && (elems[snaxSubs[jj]].d == 0.0))
1106 : ((isBwd && (elems[snaxSubs[jj]].d == 1.0))
1108 : ((!isBwd && (elems[snaxSubs[jj]].d == 1.0))
1110 : elems[snaxSubs[jj]].orderedge)));
1111 if (elems[snaxSubs[jj]].orderedge == -1)
1113 cerr <<
"Error Order not correctly assigned" << endl;
1115 if (elems[snaxSubs[jj]].orderedge == 0)
1117 needIncrement =
true;
1123 for (jj = 0; jj < int(snaxSubs.size()); ++jj)
1125 elems[snaxSubs[jj]].orderedge++;
1131 snaxSubs = ReturnDataEqualRange(edgeInds[ii], hashParent);
1132 elems[snaxSubs[0]].orderedge = 1;
1136 isOrderedOnEdge = 1;
1139 void snaxarray::CalculateTimeStepOnEdge(vector<double> &dt, vector<bool> &isSnaxDone,
int edgeInd)
1142 vector<int> snaxSubs;
1145 snaxSubs = ReturnDataEqualRange(edgeInd, hashParent);
1146 nSnax = snaxSubs.size();
1147 for (ii = 0; ii < nSnax; ++ii)
1149 isSnaxDone[snaxSubs[ii]] =
true;
1150 for (jj = ii + 1; jj < nSnax; ++jj)
1152 impactTime = SnaxImpactDt(elems[snaxSubs[ii]], elems[snaxSubs[jj]]);
1153 if (impactTime >= 0.0)
1155 dt[snaxSubs[ii]] = (dt[snaxSubs[ii]] > impactTime) ? impactTime : dt[snaxSubs[ii]];
1156 dt[snaxSubs[jj]] = (dt[snaxSubs[jj]] > impactTime) ? impactTime : dt[snaxSubs[jj]];
1162 double ValidateEquilibrateD(
double newD,
double oldD,
double stepLength)
1164 double maxLim = pow(stepLength, 1.5);
1165 double minLim = pow(stepLength, 0.5);
1168 if (!isfinite(newD))
1172 else if (newD < minLim)
1176 else if (newD > maxLim)
1183 if (!isfinite(newD))
1187 else if (newD < (1.0 - maxLim))
1189 newD = (1.0 - maxLim);
1191 else if (newD > (1.0 - minLim))
1193 newD = (1.0 - minLim);
1200 std::pair<double, double> EquilibrateEdge(
snake &snakein,
int snaxA,
int snaxB,
int vertA,
int vertB)
1205 c = snakein.snakeconn.verts.isearch(snaxA)->coord;
1206 c.add(snakein.snakeconn.verts.isearch(snaxB)->coord);
1209 del1 = snakein.snakeconn.verts.isearch(vertA)->coord;
1210 c.substract(snakein.snakeconn.verts.isearch(vertB)->coord);
1211 del1.substract(snakein.snakeconn.verts.isearch(vertB)->coord);
1212 vec = del1.cross(c.usedata());
1215 double d = vec.dot(snakein.snakeconn.verts.isearch(vertA)->coord);
1218 del1 = snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxA)->tovert)->coord;
1219 del1.substract(snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxA)->fromvert)->coord);
1220 dg0 = vec.dot(snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxA)->fromvert)->coord);
1221 double dga = vec.dot(del1.usedata());
1222 double da = (d - dg0) / dga;
1225 dg0 = vec.dot(snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxB)->fromvert)->coord);
1226 del1 = snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxB)->tovert)->coord;
1227 del1.substract(snakein.snakemesh()->verts.isearch(snakein.snaxs.isearch(snaxB)->fromvert)->coord);
1228 double dgb = vec.dot(del1.usedata());
1229 double db = (d - dg0) / dgb;
1234 void DisplayVectorArray(
const std::vector<std::array<int, 2>> &in)
1236 int count = in.size();
1237 std::cout << count <<
",";
1242 int count2 = in[0].size();
1243 std::cout << count2 <<
" : ";
1244 for (
int i = 0; i < count; ++i)
1246 for (
int j = 0; j < count2; ++j)
1248 std::cout << in[i][j] <<
" ";
1255 int SmoothStep_bordersetting(
int spawnVert,
snake &snakein,
double spawnDist)
1260 double spawnDistTol = spawnDist * 1.1;
1261 snaxInds.reserve(20);
1262 for (
auto parentEdge : snakein.snakemesh()->verts.isearch(spawnVert)->edgeind)
1264 std::vector<int> snaxIndsTemp;
1265 snaxIndsTemp.reserve(20);
1266 snakein.snaxs.findsiblings(parentEdge, snaxIndsTemp);
1268 for (
auto snaxCandidate : snaxIndsTemp)
1270 auto currSnax = snakein.snaxs(snaxCandidate);
1271 if (currSnax->CloseToVertex() == spawnVert &&
1272 snaxInds.find(currSnax->index) == rsvs3d::constants::__notfound &&
1273 (currSnax->d < spawnDistTol || (1 - spawnDistTol) < currSnax->d))
1275 snaxInds.push_back(currSnax->index);
1279 if (snaxInds.size() < 2)
1284 for (
auto iSnax : snaxInds.vec)
1286 for (
auto iSurf : snakein.snakeconn.verts.isearch(iSnax)->elmind(snakein.snakeconn, 2))
1288 bool isSpawned =
false;
1289 for (
auto iVert : snakein.snakeconn.surfs.isearch(iSurf)->vertind(snakein.snakeconn))
1291 if (iVert == rsvs3d::constants::__notfound)
1297 if (!isSpawned && borderSurfs.find(iSurf) == rsvs3d::constants::__notfound)
1299 borderSurfs.push_back(iSurf);
1307 std::vector<std::array<int, 2>> externalLinks;
1308 externalPts.reserve(snaxInds.size());
1309 externalLinks.reserve(snaxInds.size());
1310 for (
auto iSnax : snaxInds.vec)
1312 for (
auto iEdge : snakein.snakeconn.verts.isearch(iSnax)->edgeind)
1314 for (
auto iVert : snakein.snakeconn.edges.isearch(iEdge)->vertind)
1316 if (snaxInds.find(iVert) == rsvs3d::constants::__notfound)
1318 externalPts.push_back(iSnax);
1319 externalLinks.push_back({iEdge, iVert});
1325 std::vector<int> edgeProcess;
1326 edgeProcess.reserve(borderSurfs.size());
1327 for (
auto border : borderSurfs.vec)
1329 bool success =
false;
1330 for (
auto iEdge : snakein.snakeconn.surfs.isearch(border)->edgeind)
1332 auto &vertTemp = snakein.snakeconn.edges.isearch(iEdge)->vertind;
1333 if (snaxInds.find(vertTemp[0]) != rsvs3d::constants::__notfound &&
1334 snaxInds.find(vertTemp[1]) != rsvs3d::constants::__notfound && success)
1337 edgeProcess.pop_back();
1340 else if (snaxInds.find(vertTemp[0]) != rsvs3d::constants::__notfound &&
1341 snaxInds.find(vertTemp[1]) != rsvs3d::constants::__notfound)
1344 edgeProcess.push_back(iEdge);
1349 edgeProcess.push_back(rsvs3d::constants::__notfound);
1354 std::vector<double> newD;
1355 std::vector<int> countAccess;
1356 newD.assign(snaxInds.size(), 0.0);
1357 countAccess.assign(snaxInds.size(), 0);
1358 int count1 = edgeProcess.size();
1359 for (
int i = 0; i < count1; ++i)
1361 int actSurf = borderSurfs[i];
1362 int iEdge = edgeProcess[i];
1363 if (iEdge == rsvs3d::constants::__notfound)
1368 int snaxA = snakein.snakeconn.edges.isearch(iEdge)->vertind[0];
1369 int snaxB = snakein.snakeconn.edges.isearch(iEdge)->vertind[1];
1371 int posA = rsvs3d::constants::__notfound;
1372 int posB = rsvs3d::constants::__notfound;
1373 bool success =
false;
1375 for (
auto iA : externalPts.findall(snaxA))
1379 auto testEdge = snakein.snakeconn.edges.isearch(externalLinks[posA][0]);
1380 if (actSurf == testEdge->surfind[0] || actSurf == testEdge->surfind[1])
1388 std::cerr << snaxA <<
" " << posA <<
" | ";
1389 DisplayVector(externalPts.vec);
1390 DisplayVector(borderSurfs.vec);
1391 DisplayVector(edgeProcess);
1392 DisplayVectorArray(externalLinks);
1393 std::cerr << std::endl;
1394 snakein.snakeconn.edges.isearch(iEdge)->disp();
1395 snakein.snakeconn.surfs.isearch(actSurf)->disp();
1396 snakein.snakeconn.verts.isearch(snaxA)->disp();
1400 for (
auto iA : externalPts.findall(snaxB))
1404 if (borderSurfs.find(actSurf) != rsvs3d::constants::__notfound)
1406 auto testEdge = snakein.snakeconn.edges.isearch(externalLinks[posA][0]);
1407 if (actSurf == testEdge->surfind[0] || actSurf == testEdge->surfind[1])
1419 int vertA = externalLinks[posA][1];
1420 int vertB = externalLinks[posB][1];
1421 auto tempD = EquilibrateEdge(snakein, snaxA, snaxB, vertA, vertB);
1422 posA = snaxInds.find(snaxA);
1423 posB = snaxInds.find(snaxB);
1424 ValidateEquilibrateD(tempD.first, snakein.snaxs.isearch(snaxA)->d, spawnDist);
1426 newD[posA] += ValidateEquilibrateD(tempD.first, snakein.snaxs.isearch(snaxA)->d, spawnDist);
1427 countAccess[posA]++;
1429 newD[posB] += ValidateEquilibrateD(tempD.second, snakein.snaxs.isearch(snaxB)->d, spawnDist);
1430 countAccess[posB]++;
1435 int count = snaxInds.size();
1437 for (
int i = 0; i < count; ++i)
1439 if (countAccess[i] > 0)
1441 if ((newD[i] < 0.0 || countAccess[i] != 2 || newD[i] / countAccess[i] > 1.0) &&
false)
1443 DisplayVector(newD);
1444 DisplayVector(countAccess);
1446 DisplayVector(externalPts.vec);
1447 DisplayVector(snaxInds.vec);
1448 DisplayVector(borderSurfs.vec);
1449 DisplayVector(edgeProcess);
1456 snakein.snaxs[snakein.snaxs.find(snaxInds[i],
true)].d = newD[i] / double(countAccess[i]);
1465 namespace smoothsnaking
1479 double spawnDistTol = spawnDist * 1.1;
1480 snaxInds.reserve(20);
1481 for (
auto parentEdge : snakein.snakemesh()->verts.isearch(spawnVert)->edgeind)
1483 std::vector<int> snaxIndsTemp;
1484 snaxIndsTemp.reserve(20);
1485 snakein.snaxs.findsiblings(parentEdge, snaxIndsTemp);
1487 for (
auto snaxCandidate : snaxIndsTemp)
1489 auto currSnax = snakein.snaxs(snaxCandidate);
1490 if (currSnax->CloseToVertex() == spawnVert &&
1491 snaxInds.find(currSnax->index) == rsvs3d::constants::__notfound &&
1492 (currSnax->d < spawnDistTol || (1.0 - spawnDistTol) < currSnax->d))
1494 snaxInds.push_back(currSnax->index);
1500 int LaplacianSmoothingDirection(
const snake &snakein,
const vert *vertsmooth,
coordvec &smoothDir)
1502 return VertexLaplacianVector(snakein.snakeconn, vertsmooth, smoothDir,
true);
1524 int SmoothStep_sphere(
int spawnVert,
snake &snakein,
double spawnDist)
1529 rsvs3d::smoothsnaking::FindSnaxInds(snaxInds, spawnVert, snakein, spawnDist);
1530 if (snaxInds.size() < 2)
1538 std::vector<int> externalEdges, externalPts, externalSurfsPairs, externalEdgesOrder, internalPts,
1540 externalPts.reserve(snaxInds.size());
1541 externalEdges.reserve(snaxInds.size());
1542 internalPts.reserve(snaxInds.size());
1543 externalSurfsPairs.reserve(snaxInds.size() * 2);
1545 for (
auto iSnax : snaxInds.vec)
1547 for (
auto iEdge : snakein.snakeconn.verts.isearch(iSnax)->edgeind)
1549 auto currEdge = snakein.snakeconn.edges.isearch(iEdge);
1550 for (
auto iVert : currEdge->vertind)
1552 if (snaxInds.find(iVert) == rsvs3d::constants::__notfound)
1554 internalPts.push_back(iSnax);
1555 externalEdges.push_back(iEdge);
1556 externalPts.push_back(iVert);
1557 externalSurfsPairs.push_back(currEdge->surfind[0]);
1558 externalSurfsPairs.push_back(currEdge->surfind[1]);
1559 externalEdgesOrder.push_back(k++);
1564 int retValue =
OrderList(externalEdgesOrder, externalSurfsPairs,
false,
true);
1565 int nVerts = externalEdgesOrder.size();
1566 if (retValue != rsvs3d::constants::ordering::ordered)
1575 std::vector<const std::vector<double> *> vecPts;
1576 vecPts.reserve(nVerts);
1577 internalPtsOrdered.reserve(nVerts);
1578 for (
int i = 0; i < nVerts; ++i)
1580 vecPts.push_back(&(snakein.snakeconn.verts.isearch(externalPts[externalEdgesOrder[i]])->coord));
1582 auto ¢re = snakein.snakemesh()->verts.isearch(spawnVert)->coord;
1583 std::tuple<coordvec, double> centreData;
1588 catch (exception
const &ex)
1595 coordvec &vertNormal = get<0>(centreData);
1596 if (rsvs3d::utils::IsAproxEqual(vertNormal.GetNorm(), 0.0))
1603 internalPtsOrdered.reserve(nVerts);
1604 int v1 = rsvs3d::constants::__notfound;
1605 int v2 = rsvs3d::constants::__notfound;
1606 for (
int i = 0; i < nVerts; ++i)
1608 internalPtsOrdered.push_back(internalPts[externalEdgesOrder[i]]);
1610 v1 = internalPts[externalEdgesOrder[0]];
1611 int edgeAfterV2 = rsvs3d::constants::__notfound;
1612 for (
int i = 1; i < nVerts; ++i)
1614 if (v1 != internalPtsOrdered[i])
1616 v2 = internalPtsOrdered[i];
1617 edgeAfterV2 = externalEdges[externalEdgesOrder[i]];
1621 if (v2 == rsvs3d::constants::__notfound)
1626 int edgeInd = snakein.snakeconn.EdgeFromVerts(v1, v2);
1627 if (edgeInd == rsvs3d::constants::__notfound)
1632 unique(internalPtsOrdered);
1633 if (internalPtsOrdered.back() == internalPtsOrdered[0])
1635 internalPtsOrdered.pop_back();
1637 if (internalPtsOrdered.size() < 2)
1642 int surfInd = snakein.snakeconn.
SurfFromEdges(edgeInd, edgeAfterV2);
1643 #ifdef RSVS_DIAGNOSTIC
1644 std::cerr << std::endl;
1645 std::cerr <<
"snaxInds ";
1646 DisplayVector(snaxInds.vec);
1647 std::cerr << std::endl;
1648 std::cerr <<
"internalPtsOrdered ";
1649 DisplayVector(internalPtsOrdered);
1650 std::cerr << std::endl;
1651 std::cerr <<
"centre ";
1652 DisplayVector(centre);
1653 std::cerr << std::endl;
1654 std::cerr <<
"outer surfPts ";
1655 DisplayVector(internalPts);
1656 std::cerr << std::endl;
1657 std::cerr <<
"vertNormal ";
1658 DisplayVector(vertNormal.usedata());
1659 std::cerr << std::endl;
1660 snakein.snakeconn.surfs.isearch(surfInd)->disp();
1661 snakein.snakeconn.edges.isearch(edgeInd)->disp();
1664 snakein.snakeconn.surfs.isearch(surfInd)->OrderedVerts(&snakein.snakeconn, internalPts);
1665 int flipMultiplier =
1667 if (flipMultiplier == -1)
1669 vertNormal.flipsign();
1671 vertNormal.Normalize();
1673 #ifdef RSVS_DIAGNOSTIC
1674 std::cerr <<
" isSameOrder " << isSameOrder <<
" flipMultiplier " << flipMultiplier << std::endl;
1696 if (!snakein.isMeshVertIn[snakein.snakemesh()->verts.find(spawnVert)])
1699 vertNormal.flipsign();
1701 double maxOffset = 0.0;
1702 for (
auto iEdge : externalEdges)
1704 double maxOffsetTemp = snakein.snakeconn.edges.isearch(iEdge)->Length(snakein.snakeconn);
1705 maxOffset = max(maxOffsetTemp, maxOffset);
1707 double minEdgeLength = 0.0;
1708 for (
auto iSnax : snaxInds.vec)
1710 int iEdge = snakein.snaxs.isearch(iSnax)->edgeind;
1711 double minTemp = snakein.snakemesh()->edges.isearch(iEdge)->Length(*snakein.snakemesh());
1712 minEdgeLength = max(minTemp, minEdgeLength);
1715 double offsetMultiplier = 1.0 - (2.0 * get<1>(centreData) / (2.0 * M_PI));
1716 if (offsetMultiplier < 0.0)
1720 offsetMultiplier = min(max(offsetMultiplier, 0.0), 1.0);
1721 double offset = offsetMultiplier * maxOffset;
1722 vertNormal.mult(offset);
1732 double sphereRadius = offset + radiusStep * minEdgeLength * spawnDist;
1733 std::vector<double> newD;
1735 newD.reserve(snaxInds.vec.size());
1736 double maxNew = 0.0;
1737 double infVal = -INFINITY;
1738 bool allNegErr =
false;
1739 auto errValFunc = [&](
coordvec &lineVec) ->
double {
return spawnDist * minEdgeLength / lineVec.GetNorm(); };
1740 for (
auto iSnax : snaxInds.vec)
1743 int farVert = snakein.snaxs.isearch(iSnax)->CloseToVertex(
true);
1744 lineVec.substractfrom(snakein.snakemesh()->verts.isearch(farVert)->coord);
1748 newD.push_back(min(ds[0], ds[1]));
1750 else if (!isfinite(ds[0]) && ds[0] < -1e+300)
1752 newD.push_back(infVal);
1756 std::cerr <<
"ds : " << ds[0] <<
" " << ds[1] << std::endl;
1757 if (!isfinite(ds[0]))
1759 std::cerr << std::endl;
1760 int count = vecPts.size();
1761 DisplayVector(centre);
1762 for (
int i = 0; i < count; ++i)
1764 std::cerr << std::endl;
1765 DisplayVector(*vecPts[i]);
1778 newD.push_back(errValFunc(lineVec));
1783 if (fabs(ds[dUse]) <= fabs(ds[1 - dUse]))
1785 newD.push_back(ds[dUse]);
1792 newD.push_back(errValFunc(lineVec));
1795 #ifdef RSVS_DIAGNOSTIC
1796 std::cerr <<
"ds : " << ds[0] <<
" " << ds[1] << std::endl;
1799 maxNew = max(maxNew, newD.back());
1801 #ifdef RSVS_DIAGNOSTIC
1802 std::cerr << radiusStep << std::endl <<
"newD : ";
1803 DisplayVector(newD);
1804 std::cerr << std::endl;
1811 double scaleInfinite = 10.0;
1812 double scaleVals = spawnDist / (maxNew);
1813 double minD = spawnDist / (scaleInfinite);
1814 double maxD = scaleInfinite * spawnDist;
1816 int count = snaxInds.vec.size();
1818 auto edgeScale = [&](
coordvec &lineVec) ->
double {
return minEdgeLength / lineVec.GetNorm(); };
1819 for (
int i = 0; i < count; ++i)
1822 int farVert = snakein.snaxs.isearch(snaxInds[i])->CloseToVertex(
true);
1823 lineVec.substractfrom(snakein.snakemesh()->verts.isearch(farVert)->coord);
1824 double edgeScaleCurr = edgeScale(lineVec);
1826 newD[i] = scaleVals * newD[i];
1827 newD[i] = (isfinite(newD[i]) ? newD[i] : maxD * edgeScaleCurr);
1830 newD[i] = max(minD * edgeScaleCurr, newD[i]);
1833 for (
int i = 0; i < count; ++i)
1835 int j = snakein.snaxs.find(snaxInds[i],
true);
1837 snakein.snaxs[j].d = snakein.snaxs(j)->fromvert == spawnVert ? newD[i] : 1.0 - newD[i];
1838 snakein.snaxs[j].ValidateDistance(snakein);
1844 int SmoothStep_planematching(
int spawnVert,
snake &snakein,
double spawnDist)
1849 double spawnDistTol = spawnDist * 1.1;
1850 snaxInds.reserve(20);
1851 for (
auto parentEdge : snakein.snakemesh()->verts.isearch(spawnVert)->edgeind)
1853 std::vector<int> snaxIndsTemp;
1854 snaxIndsTemp.reserve(20);
1855 snakein.snaxs.findsiblings(parentEdge, snaxIndsTemp);
1857 for (
auto snaxCandidate : snaxIndsTemp)
1859 auto currSnax = snakein.snaxs(snaxCandidate);
1860 if (currSnax->CloseToVertex() == spawnVert &&
1861 snaxInds.find(currSnax->index) == rsvs3d::constants::__notfound &&
1862 (currSnax->d < spawnDistTol || (1 - spawnDistTol) < currSnax->d))
1864 snaxInds.push_back(currSnax->index);
1868 if (snaxInds.size() < 2)
1875 std::vector<std::array<int, 2>> externalLinks;
1876 externalPts.reserve(snaxInds.size());
1877 externalLinks.reserve(snaxInds.size());
1878 for (
auto iSnax : snaxInds.vec)
1880 for (
auto iEdge : snakein.snakeconn.verts.isearch(iSnax)->edgeind)
1882 for (
auto iVert : snakein.snakeconn.edges.isearch(iEdge)->vertind)
1884 if (snaxInds.find(iVert) == rsvs3d::constants::__notfound)
1886 externalPts.push_back(iSnax);
1887 externalLinks.push_back({iEdge, iVert});
1893 std::vector<int> edgeProcess;
1894 edgeProcess.reserve(externalPts.size());
1895 for (
auto iSnax : snaxInds.vec)
1897 for (
auto iEdge : snakein.snakeconn.verts.isearch(iSnax)->edgeind)
1899 int iVert1 = snakein.snakeconn.edges.isearch(iEdge)->vertind[0];
1900 int iVert2 = snakein.snakeconn.edges.isearch(iEdge)->vertind[1];
1901 if (externalPts.find(iVert1) != rsvs3d::constants::__notfound &&
1902 externalPts.find(iVert2) != rsvs3d::constants::__notfound)
1904 edgeProcess.push_back(iEdge);
1909 std::vector<double> newD;
1910 newD.assign(externalPts.size(), 0.0);
1912 for (
auto iEdge : edgeProcess)
1915 int snaxA = snakein.snakeconn.edges.isearch(iEdge)->vertind[0];
1916 int snaxB = snakein.snakeconn.edges.isearch(iEdge)->vertind[1];
1917 int vertA = externalLinks[externalPts.find(snaxA)][1];
1918 int vertB = externalLinks[externalPts.find(snaxB)][1];
1919 auto tempD = EquilibrateEdge(snakein, snaxA, snaxB, vertA, vertB);
1920 newD[externalPts.find(snaxA)] += tempD.first;
1921 newD[externalPts.find(snaxB)] += tempD.second;
1927 int count = externalPts.size();
1928 for (
int i = 0; i < count; ++i)
1930 if (newD[i] < __DBL_EPSILON__)
1932 DisplayVector(newD);
1933 DisplayVector(externalPts.vec);
1934 DisplayVector(edgeProcess);
1938 snakein.snaxs[snakein.snaxs.find(externalPts[i],
true)].d = newD[i] / 2.0;
1944 int SmoothStep_itersmooth(
int spawnVert,
snake &snakein,
double spawnDist)
1952 double stepDamping = 2.0 / double(nIter + 1);
1956 rsvs3d::smoothsnaking::FindSnaxInds(snaxInds, spawnVert, snakein, spawnDist);
1957 if (snaxInds.size() < 2)
1963 bool succesOrdering =
true;
1964 for (
auto iVert : snaxInds.vec)
1966 int vertOrdered = snakein.snakeconn.OrderVertexEdges(iVert);
1967 succesOrdering = (vertOrdered == rsvs3d::constants::ordering::ordered);
1969 if (!succesOrdering)
1976 std::vector<double> dSteps;
1977 int nSnax = snaxInds.vec.size();
1978 dSteps.reserve(nSnax);
1980 for (
int stepNum = 0; stepNum < nIter; ++stepNum)
1983 double maxD = -INFINITY;
1984 double minD = INFINITY;
1986 double minEdgeLength = INFINITY;
1987 double maxEdgeLength = -INFINITY;
1988 double sumEdgeL = 0.0;
1989 for (
auto iVert : snaxInds.vec)
1991 rsvs3d::smoothsnaking::LaplacianSmoothingDirection(snakein, snakein.snakeconn.verts.isearch(iVert),
1993 snakein.snakemesh()->VerticesVector(spawnVert, snakein.snaxs.isearch(iVert)->CloseToVertex(
true), snaxDir);
1994 minEdgeLength = min(minEdgeLength, snaxDir.GetNorm());
1995 maxEdgeLength = max(maxEdgeLength, snaxDir.GetNorm());
1996 sumEdgeL += snaxDir.GetNorm();
1997 double edgeL = snaxDir.Normalize();
1998 double dStep = snaxDir.dot(smoothDir.usedata()) / edgeL;
1999 dStep = isfinite(dStep) ? dStep : 0.0;
2000 dSteps.push_back(dStep);
2003 maxD = max(dStep, maxD);
2004 minD = min(dStep, minD);
2006 double maxAbs = max(max(fabs(maxD), fabs(minD)), spawnDist);
2008 double stepMultiplier = (spawnDist * stepDamping) / maxAbs;
2010 for (
int i = 0; i < nSnax; ++i)
2012 int j = snakein.snaxs.find(snaxInds[i],
true);
2013 double l = snakein.edgeStepLimit[snakein.snakemesh()->edges.find(snakein.snaxs(j)->edgeind)];
2014 double tempStep = (snakein.snaxs(j)->fromvert == spawnVert ? dSteps[i] : -dSteps[i]) * stepMultiplier * l;
2015 double prevD = snakein.snaxs[j].d;
2016 snakein.snaxs[j].d += tempStep;
2017 stringstream errstr;
2018 errstr <<
"Attempted to take a step of length " << tempStep <<
" snaxel->d: " << prevD;
2019 errstr <<
" Step " << stepNum <<
" of " << nIter;
2020 errstr <<
" maxD " << maxD <<
" minD " << minD <<
" l " << l <<
"dSteps : ";
2021 PrintVector(dSteps, errstr);
2022 errstr << std::endl;
2025 snakein.snaxs[j].ValidateDistance(snakein);
2027 catch (
const exception &exc)
2030 snakein.snaxs[j].d =
2031 snakein.snaxs[j].d < 0.5 ? spawnDist / double(nIter) : 1.0 - spawnDist / double(nIter);
2033 #ifdef RSVS_DIAGNOSTIC_RESOLVED
2034 std::cout << errstr.str();
2037 snakein.snaxs.PrepareForUse();
2038 snakein.UpdateCoord(snaxInds.vec);
2043 for (
auto iSnax : snaxInds.vec)
2045 totD += snakein.snaxs.isearch(iSnax)->d < 0.5 ? snakein.snaxs.isearch(iSnax)->d
2046 : 1.0 - snakein.snaxs.isearch(iSnax)->d;
2048 std::cout <<
" totD " << totD / snaxInds.size();
2049 return snaxInds.size();
2052 int SmoothStep(
int spawnVert,
snake &snakein,
double spawnDist, std::string str)
2054 static bool errHit =
false;
2056 if (rsvs3d::utils::IsAproxEqual(spawnDist, 0.0))
2060 if (str.compare(
"none") == 0 || str.compare(
"") == 0)
2064 else if (str.compare(
"laplacian") == 0)
2066 return SmoothStep_itersmooth(spawnVert, snakein, spawnDist);
2068 else if (str.compare(
"planar") == 0)
2070 return SmoothStep_planematching(spawnVert, snakein, spawnDist);
2072 else if (str.compare(
"sphere") == 0)
2074 return SmoothStep_sphere(spawnVert, snakein, spawnDist);
2081 stringstream errstr;
2082 errstr <<
"unrecognised smooth snaking step type: '" << str <<
"' defaulting to 'none'.";
2089 void snake::TakeSpawnStep(
int minIndex,
double stepLength)
2091 int nSnax = this->snaxs.size();
2092 std::vector<int> spawnVerts;
2093 spawnVerts.reserve(nSnax);
2094 for (
int i = 0; i < nSnax; ++i)
2096 if (this->snaxs(i)->index > minIndex)
2098 this->snaxs.elems[i].TakeSpawnStep(*
this, stepLength);
2103 void snake::TakeSmoothSpawnStep(
int minIndex,
double stepLength, std::string smoothStep)
2105 int nSnax = this->snaxs.size();
2106 std::vector<int> spawnVerts;
2107 spawnVerts.reserve(nSnax);
2108 for (
int i = 0; i < nSnax; ++i)
2110 if (this->snaxs(i)->index > minIndex)
2112 spawnVerts.push_back(this->snaxs(i)->CloseToVertex());
2118 for (
auto spawnVert : spawnVerts)
2120 numSuccess += SmoothStep(spawnVert, *
this, stepLength, smoothStep);
2121 this->snaxs.ForceArrayReady();
2124 std::cout << std::endl <<
"Number of successful smoothed steps : " << numSuccess << std::endl;
2128 void snax::TakeSpawnStep(
snake &snakein,
double stepLength)
2130 if (rsvs3d::utils::IsAproxEqual(stepLength, 0.0))
2134 if (stepLength < -__DBL_EPSILON__ || stepLength >= 0.5)
2138 int closeVert = this->fromvert;
2141 closeVert = this->tovert;
2142 stepLength = -stepLength;
2145 double minEdgeLength = INFINITY;
2146 for (
auto edgeInd : snakein.snakemesh()->verts.isearch(closeVert)->edgeind)
2148 double testLength = snakein.snakemesh()->edges.isearch(edgeInd)->Length(*snakein.snakemesh());
2149 minEdgeLength = testLength < minEdgeLength ? testLength : minEdgeLength;
2152 stepLength * minEdgeLength / snakein.snakemesh()->edges.isearch(this->edgeind)->Length(*snakein.snakemesh());
2153 int nEdge = snakein.snaxs.countparent(this->edgeind);
2154 this->d += stepLength;
2155 if (this->d < 0 || this->d > 1.0)
2166 std::vector<int> snaxSubs;
2167 snakein.snaxs.findsiblings(this->edgeind, snaxSubs);
2168 for (
auto snaxtest : snaxSubs)
2170 auto tempSnax = snakein.snaxs(snaxtest);
2171 if (this->index != tempSnax->index)
2173 if (!((tempSnax->d < 0.5) ^ (this->d < 0.5)))
2175 if (fabs(tempSnax->d - 0.5) > fabs(this->d))
2177 this->d = tempSnax->d;
2185 std::cout <<
" " << nChanges <<
"," << this->d <<
",";
2194 void snax::ValidateDistance(
snake &snakein)
2196 int nEdge = snakein.snaxs.countparent(this->edgeind);
2197 if (this->d < 0 || this->d > 1.0)
2199 stringstream errstr;
2200 errstr <<
"Distance should be between 0 and 1 was " << this->d;
2209 static std::vector<int> snaxSubs;
2211 snakein.snaxs.findsiblings(this->edgeind, snaxSubs);
2212 for (
auto snaxtest : snaxSubs)
2214 auto tempSnax = snakein.snaxs(snaxtest);
2215 if (this->index != tempSnax->index)
2219 bool snaxDifferentDir = this->fromvert != tempSnax->fromvert;
2222 bool inOrder = tempSnax->fromvert < tempSnax->tovert;
2224 bool tempIsAfter = this->orderedge < tempSnax->orderedge;
2227 if (snaxDifferentDir)
2229 this->d = 1.0 - this->d;
2237 if ((inOrder ^ tempIsAfter) && this->d < tempSnax->d)
2239 this->d = tempSnax->d;
2241 else if (!(inOrder ^ tempIsAfter) && this->d > tempSnax->d)
2243 this->d = tempSnax->d;
2246 if (snaxDifferentDir)
2248 this->d = 1.0 - this->d;
2259 void snax::Direction(
const snake &snakein,
coordvec &dir)
const
2261 snakein.snakemesh()->VerticesVector(this->fromvert, this->tovert, dir);
2266 void snake::ForceCloseContainers()
2268 this->snakeconn.ForceCloseContainers();
2271 snaxsurfs.elems.clear();
2272 snaxsurfs.Init(snakeconn.surfs.size());
2273 snaxsurfs.PopulateIndices();
2274 snaxsurfs.HashArray();
2275 this->SetSnaxSurfs();
2279 void snake::CalculateTimeStep(vector<double> &dt,
double dtDefault,
double distDefault)
2281 int nSnax, ii, nEdge;
2282 vector<bool> isSnaxDone;
2283 double newMindDt = dtDefault;
2284 nSnax = snaxs.size();
2285 isSnaxDone.assign(nSnax,
false);
2287 if (!snaxs.checkready())
2289 snaxs.PrepareForUse();
2291 if (this->snaxDistanceLimit_conserveShape)
2293 for (
int i = 0; i < nSnax; ++i)
2295 if (fabs(snaxs(i)->v > __DBL_EPSILON__))
2297 newMindDt = distDefault / fabs(snaxs(i)->v);
2298 dtDefault = newMindDt < dtDefault ? newMindDt : dtDefault;
2303 dt.assign(nSnax, dtDefault);
2306 for (ii = 0; ii < nSnax; ++ii)
2308 if (!isSnaxDone[ii])
2310 nEdge = snaxs.countparent(snaxs(ii)->edgeind);
2313 isSnaxDone[ii] =
true;
2317 snaxs.CalculateTimeStepOnEdge(dt, isSnaxDone, snaxs(ii)->edgeind);
2321 cerr <<
"Error: hashParent was not up to date" << endl;
2322 cerr <<
"Error in " << __PRETTY_FUNCTION__ << endl;
2332 for (
int ii = 0; ii < snaxs.size(); ii++)
2334 temp = snaxs[ii].fromvert;
2335 snaxs[ii].fromvert = snaxs(ii)->tovert;
2336 snaxs[ii].tovert = temp;
2338 snaxs[ii].d = 1.0 - snaxs[ii].d;
2339 snaxs[ii].v = -snaxs[ii].v;
2341 isFlipped = !isFlipped;
2342 snaxs.ForceArrayReady();
2345 double SnaxImpactDt(
const snax &snax1,
const snax &snax2)
2350 isSameDir = snax1.fromvert == snax2.fromvert;
2352 dD = ((1.0 * !isSameDir) + (1.0 + (-2.0) * !isSameDir) * snax2.d) - snax1.d;
2353 dV = (1.0 + (-2.0) * !isSameDir) * snax2.v - snax1.v;
2355 if (rsvs3d::utils::IsAproxEqual(dD, 0.0))
2359 if (rsvs3d::utils::IsAproxEqual(dV, 0.0))
2367 void snake::SnaxImpactDetection(vector<int> &isImpact)
2370 int nSnax, ii, nEdge;
2371 vector<bool> isSnaxDone;
2373 nSnax = snaxs.size();
2374 isSnaxDone.assign(nSnax,
false);
2376 isImpact.reserve(nSnax * 2);
2378 if (!snaxs.checkready())
2380 snaxs.PrepareForUse();
2383 for (ii = 0; ii < nSnax; ++ii)
2385 if (!isSnaxDone[ii])
2387 nEdge = snaxs.countparent(snaxs(ii)->edgeind);
2390 if (rsvs3d::utils::IsAproxEqual(snaxs(ii)->d, 0.0) && (snaxs(ii)->v <= 0.0))
2392 isImpact.push_back(snaxs(ii)->index);
2393 isImpact.push_back(-1);
2395 else if (rsvs3d::utils::IsAproxEqual(snaxs(ii)->d, 1.0) && (snaxs(ii)->v >= 0.0))
2397 isImpact.push_back(snaxs(ii)->index);
2398 isImpact.push_back(-2);
2400 isSnaxDone[ii] =
true;
2404 snaxs.DetectImpactOnEdge(isImpact, isSnaxDone, snaxs(ii)->edgeind);
2408 cerr <<
"Error: hashParent was not up to date" << endl;
2409 cerr <<
"Error in " << __PRETTY_FUNCTION__ << endl;
2415 void snake::SnaxAlmostImpactDetection(vector<int> &isImpact,
double dDlim)
2418 int nVerts, nSnax, vertInd;
2419 vector<int> vertSnaxCloseCnt, vertSnaxMinInd;
2420 vector<double> vertSnaxMinD;
2424 nVerts = snakemesh()->verts.size();
2425 nSnax = snaxs.size();
2430 vertSnaxCloseCnt.assign(nVerts, 0);
2431 vertSnaxMinInd.assign(nVerts, 0);
2432 vertSnaxMinD.assign(nVerts, 1.0);
2436 for (i = 0; i < nSnax; ++i)
2439 if ((snaxs(i)->d < dDlim) && (snaxs(i)->v <= 0.0) && !rsvs3d::utils::IsAproxEqual(snaxs(i)->d, 0.0))
2442 vertInd = snaxs(i)->fromvert;
2445 else if (((1.0 - snaxs(i)->d) < dDlim) && (snaxs(i)->v >= 0.0) &&
2446 !rsvs3d::utils::IsAproxEqual(snaxs(i)->d, 1.0))
2449 vertInd = snaxs(i)->tovert;
2450 d = 1 - snaxs(i)->d;
2454 vertInd = snakemesh()->verts.find(vertInd);
2455 vertSnaxCloseCnt[vertInd]++;
2457 if (vertSnaxMinD[vertInd] >= d)
2459 vertSnaxMinD[vertInd] = d;
2460 vertSnaxMinInd[vertInd] = i;
2466 for (i = 0; i < nVerts; ++i)
2468 if (vertSnaxCloseCnt[i] >= 2)
2470 isImpact.push_back(snaxs(vertSnaxMinInd[i])->index);
2471 if (snaxs(vertSnaxMinInd[i])->d < dDlim)
2474 snaxs[vertSnaxMinInd[i]].d = 0.0;
2475 isImpact.push_back(-1);
2480 snaxs[vertSnaxMinInd[i]].d = 1.0;
2481 isImpact.push_back(-2);
2485 snaxs.PrepareForUse();
2488 void snaxarray::DetectImpactOnEdge(vector<int> &isImpact, vector<bool> &isSnaxDone,
int edgeInd)
2490 int nSnax, ii, jj, dOrd;
2491 vector<int> snaxSubs;
2493 snaxSubs = ReturnDataEqualRange(edgeInd, hashParent);
2494 nSnax = snaxSubs.size();
2495 for (ii = 0; ii < nSnax; ++ii)
2497 isSnaxDone[snaxSubs[ii]] =
true;
2499 for (jj = ii + 1; jj < nSnax; ++jj)
2501 impactTime = SnaxImpactDt(elems[snaxSubs[ii]], elems[snaxSubs[jj]]);
2502 dOrd = abs(elems[snaxSubs[ii]].orderedge - elems[snaxSubs[jj]].orderedge);
2503 if (dOrd == 1 && rsvs3d::utils::IsAproxEqual(impactTime, 0.0))
2505 isImpact.push_back((elems[snaxSubs[ii]].index));
2506 isImpact.push_back((elems[snaxSubs[jj]].index));
2508 isImpact.push_back((elems[snaxSubs[jj]].index));
2509 isImpact.push_back((elems[snaxSubs[ii]].index));
2513 if (rsvs3d::utils::IsAproxEqual(elems[snaxSubs[ii]].d, 0.0) && (elems[snaxSubs[ii]].v <= 0.0) &&
2514 elems[snaxSubs[ii]].orderedge == 1)
2516 isImpact.push_back(elems[snaxSubs[ii]].index);
2517 isImpact.push_back(-1);
2519 else if (rsvs3d::utils::IsAproxEqual(elems[snaxSubs[ii]].d, 1.0) && (elems[snaxSubs[ii]].v >= 0.0) &&
2520 elems[snaxSubs[ii]].orderedge == nSnax)
2522 isImpact.push_back(elems[snaxSubs[ii]].index);
2523 isImpact.push_back(-2);
2528 void snake::OrientFaces()
2533 if (this->Check3D())
2535 this->OrientSurfaceVolume();
2539 this->OrientEdgeSurface();
2542 void snake::OrientEdgeSurface()
2544 cerr <<
"Warning: not coded yet in " << __PRETTY_FUNCTION__ << endl;
2546 void snake::OrientSurfaceVolume()
2553 int nBlocks, ii, jj, ni, nj, kk, ll;
2554 vector<int> surfOrient;
2555 vector<bool> isFlip;
2559 nBlocks = snakeconn.OrientRelativeSurfaceVolume(surfOrient);
2560 isFlip.assign(nBlocks,
false);
2565 for (ii = 1; ii <= nBlocks; ii++)
2568 nj = surfOrient.size();
2572 while (jj < nj && ii != abs(surfOrient[jj]))
2584 kk = snakeconn.surfs(jj)->voluind[0] == 0;
2585 ll = snaxs.isearch(snakeconn.edges.isearch(snakeconn.surfs(jj)->edgeind[0])->vertind[0])->tovert;
2586 centreVolu = snakemesh()->verts.isearch(ll)->coord;
2587 ll = snaxs.isearch(snakeconn.edges.isearch(snakeconn.surfs(jj)->edgeind[0])->vertind[0])->fromvert;
2588 centreVolu.substract(snakemesh()->verts.isearch(ll)->coord);
2590 normalVec = snakeconn.CalcPseudoNormalSurf(snakeconn.surfs(jj)->index);
2592 dotProd = centreVolu.dot(normalVec.usedata());
2593 }
while (!isfinite(dotProd) || (fabs(dotProd) < numeric_limits<double>::epsilon()));
2595 isFlip[ii - 1] = (((dotProd < 0.0) && (kk == 0)) || ((dotProd > 0.0) && (kk == 1)));
2599 ni = surfOrient.size();
2600 for (ii = 0; ii < ni; ++ii)
2602 if (isFlip[abs(surfOrient[ii]) - 1])
2604 snakeconn.surfs.elems[ii].FlipVolus();
2609 void snake::AssignInternalVerts()
2615 vector<int> vertBlock;
2617 FindBlockSnakeMeshVerts(vertBlock);
2618 this->isFlipped =
false;
2619 ni = vertBlock.size();
2620 for (ii = 0; ii < ni; ++ii)
2622 isMeshVertIn[ii] = vertBlock[ii] > 0;
2625 int snake::FindBlockSnakeMeshVerts(vector<int> &vertBlock)
const
2632 int nVertExplored, nVerts, nBlocks, nCurr, nEdgesCurr, ii, jj, kk, nSnaxs, ll, nl;
2633 vector<bool> vertStatus, snaxStatus;
2635 vector<int> currQueue, nextQueue,
2639 nVerts = snakemesh()->verts.size();
2640 nSnaxs = snaxs.size();
2644 snaxStatus.assign(nSnaxs,
false);
2645 vertStatus.assign(nVerts,
false);
2646 vertBlock.assign(nVerts, 0);
2647 currQueue.reserve(nVerts / 2);
2648 nextQueue.reserve(nVerts / 2);
2651 while (nVertExplored < nSnaxs)
2654 if (currQueue.size() < 1)
2659 while (ii < nSnaxs && snaxStatus[ii])
2665 cerr <<
"Error starting point for loop not found despite max number of "
2666 "vertex not reached"
2668 cerr <<
"Error in " << __PRETTY_FUNCTION__ << endl;
2671 currQueue.push_back(snakemesh()->verts.find(snaxs(ii)->fromvert));
2675 nCurr = currQueue.size();
2678 for (ii = 0; ii < nCurr; ++ii)
2680 if (!vertStatus[currQueue[ii]])
2682 vertBlock[currQueue[ii]] = nBlocks;
2683 nEdgesCurr = snakemesh()->verts(currQueue[ii])->edgeind.size();
2684 for (jj = 0; jj < nEdgesCurr; ++jj)
2687 if (snaxs.countparent(snakemesh()->verts(currQueue[ii])->edgeind[jj]) < 1)
2690 snakemesh()->edges.isearch(snakemesh()->verts(currQueue[ii])->edgeind[jj])->vertind[0] ==
2691 snakemesh()->verts(currQueue[ii])->index);
2692 nextQueue.push_back(snakemesh()->verts.find(
2693 snakemesh()->edges.isearch(snakemesh()->verts(currQueue[ii])->edgeind[jj])->vertind[kk]));
2695 if (snakemesh()->verts.find(snakemesh()
2696 ->edges.isearch(snakemesh()->verts(currQueue[ii])->edgeind[jj])
2697 ->vertind[kk]) == -1)
2699 cerr <<
"Edge index: " << snakemesh()->verts(currQueue[ii])->edgeind[jj] <<
" vertex index:"
2701 ->edges.isearch(snakemesh()->verts(currQueue[ii])->edgeind[jj])
2704 cerr <<
"Edge connected to non existant vertex" << endl;
2705 cerr <<
"Error in " << __PRETTY_FUNCTION__ << endl;
2712 snaxs.findsiblings(snakemesh()->verts(currQueue[ii])->edgeind[jj], tempSnax);
2713 nl = tempSnax.size();
2714 for (ll = 0; ll < nl; ++ll)
2716 if (snakemesh()->verts(currQueue[ii])->index == snaxs(tempSnax[ll])->fromvert)
2718 nVertExplored += int(!snaxStatus[tempSnax[ll]]);
2719 snaxStatus[tempSnax[ll]] =
true;
2724 vertStatus[currQueue[ii]] =
true;
2730 currQueue.swap(nextQueue);
2734 grid::limits snake::Scale(
const grid::limits &newSize)
2736 auto boundBox = this->snakemesh()->BoundingBox();
2740 this->snakeconn.LinearTransform(transformation);
2743 this->snakemesh()->LinearTransformFamily(transformation);
2748 std::vector<double> snake::MoveDirections()
const
2750 std::vector<double> coords;
2751 int nVert = this->snaxs.size();
2752 coords.reserve(nVert * 3);
2757 for (
int i = 0; i < nVert; ++i)
2759 this->snaxs(i)->Direction(*
this, lapVec);
2760 for (
int j = 0; j < 3; ++j)
2762 coords.push_back(lapVec(j));
Handles the use and norm of a vector for which the norm and the unit value might be needed.
int SurfFromEdges(int e1, int e2, int repetitionBehaviour=-1) const
Returns the index of the surface connecting two edges.
void SetEdgeStepLimits()
Sets the relative edge step limits.
Class for a vertex in a mesh.
Provides all the mesh tools used for the generation of 3D grids and geometries.
std::vector< const std::vector< double > * > coordlist
Defines a list of coordinates.
std::tuple< coordvec, double > VertexNormal(const std::vector< double > ¢re, const grid::coordlist &vecPts)
Calculates the vertex normal weighted by surface angle partitions.
std::array< std::array< double, 3 >, 3 > transformation
Defines a linear transformation to the mesh where for each dimension: {new minimum,...
int OrderList(std::vector< int > &edgeind, const std::vector< int > &edge2Vert, bool warn=true, bool errout=true, const std::vector< int > *edgeIndOrigPtr=NULL)
Orders a list of elements defined by pairs of indices.
int NormalShouldFlip(const std::vector< int > orderedList, int elm1, int elm2, const std::vector< int > &voluind, bool innerComparison)
Answers if a normal should be flipped to point towards the outside of a volume.
Tools for the mathematical processing of meshes.
std::array< double, 2 > IntersectLineSphere(const coordvec &lineVec, const coordvec &offset, double sphereRadius)
Calculates the parametric position along a line at which it intersects a sphere.
Namespace for general purpose tools of the RSVS project.
int sign(T val)
Returns the sign of a type comparable to 0.
Provides various utility functions for the RSVS operation.
Provides the core restricted surface snake container.
Provides the error and warning system used by the RSVS3D project.
#define RSVS3D_ERROR_LOGIC(M)
Throw a logic_error.
#define RSVS3D_ERROR_NOTHROW(M)
Generic rsvs warning.
#define RSVS3D_ERROR(M)
Throw generic rsvs errors.
#define RSVS3D_ERROR_RANGE(M)
Throw a range_error.
#define RSVS3D_ERROR_ARGUMENT(M)
Throw a invalid_argument.
#define RSVS3D_ERROR_TYPE(M, T)
Throw a specific error type.