43 namespace NekMeshUtils
46 bool FaceMesh::ValidateCurves()
48 vector<int> curvesInSurface;
49 for (
int i = 0; i < m_edgeloops.size(); i++)
51 for (
int j = 0; j < m_edgeloops[i]->edges.size(); j++)
53 curvesInSurface.push_back(m_edgeloops[i]->edges[j]->GetId());
59 for (
int i = 0; i < curvesInSurface.size(); i++)
61 vector<EdgeSharedPtr> es =
62 m_curvemeshes[curvesInSurface[i]]->GetMeshEdges();
64 for (
int j = i; j < curvesInSurface.size(); j++)
71 vector<EdgeSharedPtr> es2 =
72 m_curvemeshes[curvesInSurface[j]]->GetMeshEdges();
74 for (
int l = 0; l < es.size(); l++)
78 for (
int k = 0; k < es2.size(); k++)
80 if (es[l]->m_n1 == es2[k]->m_n1 ||
81 es[l]->m_n1 == es2[k]->m_n2 ||
82 es[l]->m_n2 == es2[k]->m_n1 ||
83 es[l]->m_n2 == es2[k]->m_n2)
89 es2[k]->m_n1->GetCADSurfInfo(m_id);
91 es2[k]->m_n2->GetCADSurfInfo(m_id);
93 NekDouble den = (P4[0] - P3[0]) * (P2[1] - P1[1]) -
94 (P2[0] - P1[0]) * (P4[1] - P3[1]);
101 NekDouble t = ((P1[0] - P3[0]) * (P4[1] - P3[1]) -
102 (P4[0] - P3[0]) * (P1[1] - P3[1])) /
105 (P1[0] - P3[0] + t * (P2[0] - P1[0])) / (P4[0] - P3[0]);
107 if (t < 1.0 && t > 0.0 && u < 1.0 && u > 0.0)
110 uv[0] = P1[0] + t * (P2[0] - P1[0]);
111 uv[1] = P1[1] + t * (P2[1] - P1[1]);
114 <<
"Curve mesh error at " <<
loc[0] <<
" "
115 <<
loc[1] <<
" " <<
loc[2] <<
" on face " << m_id
126 void FaceMesh::ValidateLoops()
130 for (
int i = 0; i < orderedLoops.size(); i++)
132 int numPoints = orderedLoops[i].size();
136 for(
int j = 0; j < m_edgeloops[i]->edges.size(); j++)
138 int cid = m_edgeloops[i]->edges[j]->GetId();
139 m_curvemeshes[cid]->ReMesh();
151 for (
int i = 0; i < orderedLoops.size(); i++)
153 numPoints += orderedLoops[i].size();
154 for (
int j = 0; j < orderedLoops[i].size(); j++)
156 m_inBoundary.insert(orderedLoops[i][j]);
161 ss <<
"3 points required for triangulation, " << numPoints <<
" in loop"
164 for (
int i = 0; i < m_edgeloops.size(); i++)
166 for (
int j = 0; j < m_edgeloops[i]->edges.size(); j++)
168 ss << m_edgeloops[i]->edges[j]->GetId() <<
" ";
172 ASSERTL0(numPoints > 2,
"number of verts in face is less than 3");
178 vector<Array<OneD, NekDouble> > centers;
179 for (
int i = 0; i < m_edgeloops.size(); i++)
181 centers.push_back(m_edgeloops[i]->center);
184 pplanemesh->Assign(orderedLoops, centers, m_id, m_str);
188 pplanemesh->Extract(m_connec);
203 pplanemesh->AssignStiener(m_stienerpoints);
205 pplanemesh->Extract(m_connec);
218 for (
int i = 0; i < m_localElements.size(); i++)
220 vector<EdgeSharedPtr> e = m_localElements[i]->GetEdgeList();
221 for (
int j = 0; j < e.size(); j++)
223 e[j]->m_elLink.clear();
225 m_mesh->m_element[2].push_back(m_localElements[i]);
228 if (m_mesh->m_verbose)
233 cout << scientific <<
"\r\t\tFace " << m_id << endl
234 <<
"\t\t\tNodes: " << m_localNodes.size() << endl
235 <<
"\t\t\tEdges: " << m_localEdges.size() << endl
236 <<
"\t\t\tTriangles: " << m_localElements.size() << endl
237 <<
"\t\t\tLoops: " << m_edgeloops.size() << endl
238 <<
"\t\t\tSTR: " << m_str << endl
243 void FaceMesh::OptimiseLocalMesh()
255 void FaceMesh::Smoothing()
257 EdgeSet::iterator eit;
258 NodeSet::iterator nit;
262 map<int, vector<EdgeSharedPtr> > connectingedges;
264 map<int, vector<ElementSharedPtr> > connectingelements;
266 for (eit = m_localEdges.begin(); eit != m_localEdges.end(); eit++)
268 connectingedges[(*eit)->m_n1->m_id].push_back(*eit);
269 connectingedges[(*eit)->m_n2->m_id].push_back(*eit);
272 for (
int i = 0; i < m_localElements.size(); i++)
274 vector<NodeSharedPtr> v = m_localElements[i]->GetVertexList();
275 for (
int j = 0; j < 3; j++)
277 connectingelements[v[j]->m_id].push_back(m_localElements[i]);
282 for (
int q = 0; q < 4; q++)
284 for (nit = m_localNodes.begin(); nit != m_localNodes.end(); nit++)
286 NodeSet::iterator f = m_inBoundary.find((*nit));
289 if (f != m_inBoundary.end())
295 vector<NodeSharedPtr> connodes;
297 vector<EdgeSharedPtr> edges = connectingedges[(*nit)->m_id];
298 vector<ElementSharedPtr> els = connectingelements[(*nit)->m_id];
300 vector<NodeSharedPtr> nodesystem;
301 vector<NekDouble> lamp;
303 for (
int i = 0; i < edges.size(); i++)
305 vector<NekDouble> lambda;
308 if (*nit == edges[i]->m_n1)
312 else if (*nit == edges[i]->m_n2)
318 ASSERTL0(
false,
"could not find node");
324 for (
int j = 0; j < els.size(); j++)
326 vector<NodeSharedPtr> v = els[j]->GetVertexList();
329 if (v[0] == J || v[1] == J || v[2] == J)
337 vector<EdgeSharedPtr> es = els[j]->GetEdgeList();
338 for (
int k = 0; k < es.size(); k++)
340 if (!(es[k]->m_n1 == *nit || es[k]->m_n2 == *nit))
347 ASSERTL0(found,
"failed to find edge to test");
353 (
A[1] - uj[1]) * (B[0] -
A[0])) /
354 ((ui[0] - uj[0]) * (B[1] -
A[1]) -
355 (ui[1] - uj[1]) * (B[0] -
A[0]));
357 if (!(lam < 0) && !(lam > 1))
358 lambda.push_back(lam);
361 if (lambda.size() > 0)
363 sort(lambda.begin(), lambda.end());
366 ud[0] = uj[0] + lambda[0] * (ui[0] - uj[0]);
367 ud[1] = uj[1] + lambda[0] * (ui[1] - uj[1]);
370 new Node(0, locd[0], locd[1], locd[2]));
371 dn->SetCADSurf(m_cadsurf, ud);
373 nodesystem.push_back(dn);
374 lamp.push_back(lambda[0]);
378 nodesystem.push_back(J);
387 for (
int i = 0; i < nodesystem.size(); i++)
390 u0[0] += uj[0] / nodesystem.size();
391 u0[1] += uj[1] / nodesystem.size();
452 bool inbounds =
true;
453 if (u0[0] < bounds[0])
457 else if (u0[0] > bounds[1])
461 else if (u0[1] < bounds[2])
465 else if (u0[1] > bounds[3])
501 (*nit)->Move(l2, m_id, u0);
506 void FaceMesh::DiagonalSwap()
508 map<int, int> idealConnec;
509 map<int, int> actualConnec;
510 map<int, vector<EdgeSharedPtr> > nodetoedge;
512 EdgeSet::iterator eit;
513 for (eit = m_localEdges.begin(); eit != m_localEdges.end(); eit++)
515 nodetoedge[(*eit)->m_n1->m_id].push_back(*eit);
516 nodetoedge[(*eit)->m_n2->m_id].push_back(*eit);
518 NodeSet::iterator nit;
519 for (nit = m_localNodes.begin(); nit != m_localNodes.end(); nit++)
522 NodeSet::iterator f = m_inBoundary.find((*nit));
523 if (f == m_inBoundary.end())
526 idealConnec[(*nit)->m_id] = 6;
550 idealConnec[(*nit)->m_id] = 4;
553 for (nit = m_localNodes.begin(); nit != m_localNodes.end(); nit++)
555 actualConnec[(*nit)->m_id] = nodetoedge[(*nit)->m_id].size();
560 for (
int q = 0; q < 4; q++)
562 int edgesStart = m_localEdges.size();
564 m_localEdges.clear();
566 int swappedEdges = 0;
568 EdgeSet::iterator it;
570 for (it = edges.begin(); it != edges.end(); it++)
574 NodeSet::iterator f1 = m_inBoundary.find((*it)->m_n1);
575 NodeSet::iterator f2 = m_inBoundary.find((*it)->m_n2);
576 if (f1 != m_inBoundary.end() && f2 != m_inBoundary.end())
578 m_localEdges.insert(e);
588 vector<NodeSharedPtr> nt = tri1->GetVertexList();
592 if (nt[0] != n1 && nt[0] != n2)
598 else if (nt[1] != n1 && nt[1] != n2)
604 else if (nt[2] != n1 && nt[2] != n2)
612 ASSERTL0(
false,
"failed to identify verticies in tri1");
615 nt = tri2->GetVertexList();
617 if (nt[0] != n1 && nt[0] != n2)
621 else if (nt[1] != n1 && nt[1] != n2)
625 else if (nt[2] != n1 && nt[2] != n2)
631 ASSERTL0(
false,
"failed to identify verticies in tri2");
646 ai =
A->GetCADSurfInfo(m_id);
647 bi = B->GetCADSurfInfo(m_id);
648 ci = C->GetCADSurfInfo(m_id);
649 di = D->GetCADSurfInfo(m_id);
653 CDA = 0.5 * (-di[0] * ci[1] + ai[0] * ci[1] + ci[0] * di[1] -
654 ai[0] * di[1] - ci[0] * ai[1] + di[0] * ai[1]);
656 CBD = 0.5 * (-bi[0] * ci[1] + di[0] * ci[1] + ci[0] * bi[1] -
657 di[0] * bi[1] - ci[0] * di[1] + bi[0] * di[1]);
661 if (!(CDA > 0.001 && CBD > 0.001))
663 m_localEdges.insert(e);
671 int nodedefectbefore = 0;
673 abs(actualConnec[
A->m_id] - idealConnec[
A->m_id]);
675 abs(actualConnec[B->m_id] - idealConnec[B->m_id]);
677 abs(actualConnec[C->m_id] - idealConnec[C->m_id]);
679 abs(actualConnec[D->m_id] - idealConnec[D->m_id]);
681 int nodedefectafter = 0;
683 abs(actualConnec[
A->m_id] - 1 - idealConnec[
A->m_id]);
685 abs(actualConnec[B->m_id] - 1 - idealConnec[B->m_id]);
687 abs(actualConnec[C->m_id] + 1 - idealConnec[C->m_id]);
689 abs(actualConnec[D->m_id] + 1 - idealConnec[D->m_id]);
691 if (nodedefectafter < nodedefectbefore)
699 minanglebefore = min(minanglebefore,
A->Angle(B, C));
700 minanglebefore = min(minanglebefore, B->Angle(
A, C));
701 minanglebefore = min(minanglebefore, B->Angle(
A, D));
702 minanglebefore = min(minanglebefore,
A->Angle(B, D));
703 minanglebefore = min(minanglebefore, D->Angle(
A, B));
705 NekDouble minangleafter = C->Angle(B, D);
706 minangleafter = min(minangleafter, D->Angle(B, C));
707 minangleafter = min(minangleafter, B->Angle(C, D));
708 minangleafter = min(minangleafter, C->Angle(
A, D));
709 minangleafter = min(minangleafter,
A->Angle(C, D));
710 minangleafter = min(minangleafter, D->Angle(
A, C));
712 if (minangleafter > minanglebefore)
720 actualConnec[
A->m_id]--;
721 actualConnec[B->m_id]--;
722 actualConnec[C->m_id]++;
723 actualConnec[D->m_id]++;
727 CAt = std::shared_ptr<Edge>(
new Edge(C,
A));
728 ADt = std::shared_ptr<Edge>(
new Edge(
A, D));
729 DBt = std::shared_ptr<Edge>(
new Edge(D, B));
730 BCt = std::shared_ptr<Edge>(
new Edge(B, C));
732 vector<EdgeSharedPtr> es = tri1->GetEdgeList();
733 for (
int i = 0; i < 3; i++)
744 es = tri2->GetEdgeList();
745 for (
int i = 0; i < 3; i++)
758 vector<pair<ElementSharedPtr, int> > links;
760 links = CA->m_elLink;
761 CA->m_elLink.clear();
762 for (
int i = 0; i < links.size(); i++)
764 if (links[i].first->GetId() == tri1->GetId())
768 CA->m_elLink.push_back(links[i]);
771 links = BC->m_elLink;
772 BC->m_elLink.clear();
773 for (
int i = 0; i < links.size(); i++)
775 if (links[i].first->GetId() == tri1->GetId())
779 BC->m_elLink.push_back(links[i]);
782 links = AD->m_elLink;
783 AD->m_elLink.clear();
784 for (
int i = 0; i < links.size(); i++)
786 if (links[i].first->GetId() == tri2->GetId())
790 AD->m_elLink.push_back(links[i]);
793 links = DB->m_elLink;
794 DB->m_elLink.clear();
795 for (
int i = 0; i < links.size(); i++)
797 if (links[i].first->GetId() == tri2->GetId())
801 DB->m_elLink.push_back(links[i]);
806 vector<NodeSharedPtr> t1, t2;
815 m_mesh->m_spaceDim != 3);
816 vector<int> tags = tri1->GetTagList();
818 int id1 = tri1->GetId();
819 int id2 = tri2->GetId();
823 tags = tri2->GetTagList();
829 ntri1->m_parentCAD = m_cadsurf;
830 ntri2->m_parentCAD = m_cadsurf;
832 vector<EdgeSharedPtr> t1es = ntri1->GetEdgeList();
833 for (
int i = 0; i < 3; i++)
837 ntri1->SetEdge(i, DB);
838 DB->m_elLink.push_back(
839 pair<ElementSharedPtr, int>(ntri1, i));
841 else if (t1es[i] == BC)
843 ntri1->SetEdge(i, BC);
844 BC->m_elLink.push_back(
845 pair<ElementSharedPtr, int>(ntri1, i));
847 else if (t1es[i] == newe)
849 ntri1->SetEdge(i, newe);
850 newe->m_elLink.push_back(
851 pair<ElementSharedPtr, int>(ntri1, i));
855 ASSERTL0(
false,
"weird edge in new tri 1");
858 vector<EdgeSharedPtr> t2es = ntri2->GetEdgeList();
859 for (
int i = 0; i < 3; i++)
863 ntri2->SetEdge(i, CA);
864 CA->m_elLink.push_back(
865 pair<ElementSharedPtr, int>(ntri2, i));
867 else if (t2es[i] == AD)
869 ntri2->SetEdge(i, AD);
870 AD->m_elLink.push_back(
871 pair<ElementSharedPtr, int>(ntri2, i));
873 else if (t2es[i] == newe)
875 ntri2->SetEdge(i, newe);
876 newe->m_elLink.push_back(
877 pair<ElementSharedPtr, int>(ntri2, i));
881 ASSERTL0(
false,
"weird edge in new tri 2");
885 m_localEdges.insert(newe);
887 m_localElements[id1] = ntri1;
888 m_localElements[id2] = ntri2;
894 m_localEdges.insert(e);
898 ASSERTL0(m_localEdges.size() == edgesStart,
"mismatch edge count");
902 void FaceMesh::BuildLocalMesh()
909 for (
int i = 0; i < m_connec.size(); i++)
912 m_mesh->m_spaceDim != 3);
915 tags.push_back(m_compId);
918 E->m_parentCAD = m_cadsurf;
920 vector<NodeSharedPtr> nods = E->GetVertexList();
921 for (
int j = 0; j < nods.size(); j++)
924 m_localNodes.insert(nods[j]);
927 E->SetId(m_localElements.size());
928 m_localElements.push_back(E);
931 for (
int i = 0; i < m_localElements.size(); ++i)
933 for (
int j = 0; j < m_localElements[i]->GetEdgeCount(); ++j)
935 pair<EdgeSet::iterator, bool> testIns;
938 EdgeSet::iterator s = m_mesh->m_edgeSet.find(ed);
939 if (!(s == m_mesh->m_edgeSet.end()))
942 m_localElements[i]->SetEdge(j, *s);
945 testIns = m_localEdges.insert(ed);
950 ed2->m_elLink.push_back(
951 pair<ElementSharedPtr, int>(m_localElements[i], j));
956 m_localElements[i]->SetEdge(j, e2);
957 e2->m_elLink.push_back(
958 pair<ElementSharedPtr, int>(m_localElements[i], j));
964 void FaceMesh::Stretching()
970 NekDouble dxu = int(bnds[1] - bnds[0] < bnds[3] - bnds[2]
972 : (bnds[1] - bnds[0]) / (bnds[3] - bnds[2]) * 40);
973 NekDouble dxv = int(bnds[3] - bnds[2] < bnds[1] - bnds[0]
975 : (bnds[3] - bnds[2]) / (bnds[1] - bnds[0]) * 40);
977 NekDouble du = (bnds[1] - bnds[0]) / dxu;
978 NekDouble dv = (bnds[3] - bnds[2]) / dxv;
982 for (
int i = 0; i < dxu; i++)
984 for (
int j = 0; j < dxv; j++)
987 uv[0] = bnds[0] + i * du;
988 uv[1] = bnds[2] + j * dv;
999 NekDouble ru = sqrt(r[3] * r[3] + r[4] * r[4] + r[5] * r[5]);
1000 NekDouble rv = sqrt(r[6] * r[6] + r[7] * r[7] + r[8] * r[8]);
1018 bool FaceMesh::Validate()
1023 int pointBefore = m_stienerpoints.size();
1024 for (
int i = 0; i < m_connec.size(); i++)
1028 vector<Array<OneD, NekDouble> > info;
1030 for (
int j = 0; j < 3; j++)
1032 info.push_back(m_connec[i][j]->GetCADSurfInfo(m_id));
1035 r[0] = m_connec[i][0]->Distance(m_connec[i][1]);
1036 r[1] = m_connec[i][1]->Distance(m_connec[i][2]);
1037 r[2] = m_connec[i][2]->Distance(m_connec[i][0]);
1039 a[0] = m_connec[i][0]->Angle(m_connec[i][1]->GetLoc(),
1040 m_connec[i][2]->GetLoc(),
1041 m_cadsurf->N(info[0]));
1042 a[1] = m_connec[i][1]->Angle(m_connec[i][2]->GetLoc(),
1043 m_connec[i][0]->GetLoc(),
1044 m_cadsurf->N(info[1]));
1045 a[2] = m_connec[i][2]->Angle(m_connec[i][0]->GetLoc(),
1046 m_connec[i][1]->GetLoc(),
1047 m_cadsurf->N(info[2]));
1049 NekDouble d1 = m_mesh->m_octree->Query(m_connec[i][0]->GetLoc());
1050 NekDouble d2 = m_mesh->m_octree->Query(m_connec[i][1]->GetLoc());
1051 NekDouble d3 = m_mesh->m_octree->Query(m_connec[i][2]->GetLoc());
1054 uvc[0] = (info[0][0] + info[1][0] + info[2][0]) / 3.0;
1055 uvc[1] = (info[0][1] + info[1][1] + info[2][1]) / 3.0;
1058 NekDouble d4 = m_mesh->m_octree->Query(locc);
1060 NekDouble d = (d1 + d2 + d3 + d4) / 4.0;
1062 vector<bool> valid(3);
1063 valid[0] = r[0] < d * 1.5;
1064 valid[1] = r[1] < d * 1.5;
1065 valid[2] = r[2] < d * 1.5;
1067 vector<bool> angValid(3);
1068 angValid[0] = a[0] / M_PI * 180.0 > 20.0 && a[0] / M_PI * 180.0 < 120.0;
1069 angValid[1] = a[1] / M_PI * 180.0 > 20.0 && a[1] / M_PI * 180.0 < 120.0;
1070 angValid[2] = a[2] / M_PI * 180.0 > 20.0 && a[2] / M_PI * 180.0 < 120.0;
1073 int numAngValid = 0;
1074 for (
int j = 0; j < 3; j++)
1092 if (numValid != 3 || numAngValid != 3)
1119 if (m_stienerpoints.size() == pointBefore)
1133 NekDouble npDelta = m_mesh->m_octree->Query(np);
1136 new Node(m_mesh->m_numNodes++, np[0], np[1], np[2]));
1140 for (
int i = 0; i < orderedLoops.size(); i++)
1142 for (
int j = 0; j < orderedLoops[i].size(); j++)
1144 NekDouble r = orderedLoops[i][j]->Distance(n);
1146 if (r < npDelta / 2.0)
1156 for (
int i = 0; i < m_stienerpoints.size(); i++)
1158 NekDouble r = m_stienerpoints[i]->Distance(n);
1160 if (r < npDelta / 2.0)
1170 n->SetCADSurf(m_cadsurf, uv);
1171 m_stienerpoints.push_back(n);
1175 void FaceMesh::OrientateCurves()
1178 orderedLoops.clear();
1181 for (
int i = 0; i < m_edgeloops.size(); i++)
1183 vector<NodeSharedPtr> cE;
1184 for (
int j = 0; j < m_edgeloops[i]->edges.size(); j++)
1186 int cid = m_edgeloops[i]->edges[j]->GetId();
1187 vector<NodeSharedPtr> edgePoints =
1188 m_curvemeshes[cid]->GetMeshPoints();
1190 int numPoints = m_curvemeshes[cid]->GetNumPoints();
1194 for (
int k = 0; k < numPoints - 1; k++)
1196 cE.push_back(edgePoints[k]);
1201 for (
int k = numPoints - 1; k > 0; k--)
1203 cE.push_back(edgePoints[k]);
1207 orderedLoops.push_back(cE);
#define ASSERTL0(condition, msg)
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
Represents an edge which joins two points.
Represents a point in the domain.
std::unordered_set< EdgeSharedPtr, EdgeHash > EdgeSet
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
ElementFactory & GetElementFactory()
std::shared_ptr< TriangleInterface > TriangleInterfaceSharedPtr
std::shared_ptr< Element > ElementSharedPtr
std::shared_ptr< Node > NodeSharedPtr
Basic information about an element.