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");
352 NekDouble lam = ((A[0] - uj[0]) * (B[1] - A[1]) -
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)
698 NekDouble minanglebefore = C->Angle(A, B);
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)
Basic information about an element.
Represents an edge which joins two points.
std::unordered_set< EdgeSharedPtr, EdgeHash > EdgeSet
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
ElementFactory & GetElementFactory()
std::shared_ptr< Node > NodeSharedPtr
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
std::shared_ptr< Element > ElementSharedPtr
std::shared_ptr< TriangleInterface > TriangleInterfaceSharedPtr