33 for(
size_t i = 0; i <
faces.size(); i++) {
34 std::vector<GEdge *> e =
faces[i]->edges();
35 if(std::find(e.begin(), e.end(), ge1) != e.end() &&
36 std::find(e.begin(), e.end(), ge2) != e.end())
43 std::vector<MTriangle *> &mesh,
44 std::vector<MVertex *> &new_vertices)
54 new_vertices =
f.mesh_vertices;
56 f.mesh_vertices.clear();
117 mutable std::map<std::pair<GFace *, GFace *>, std::vector<MVertex *> >
143 for(
size_t i = 0; i <
_normals.size(); i++) {
192 std::map<MFace, SVector3, MFaceLessThan> t_normals;
194 for(
int j = 0; j < 4; j++) {
196 auto it = t_normals.find(
f);
197 if(it == t_normals.end()) {
202 if(
dot(t, n) < 0) n *= -1.0;
214 for(
size_t i = 0; i < bls.size(); i++) {
215 for(
size_t j = 0; j < bls[i]->triangles.size(); j++) {
216 for(
int k = 0; k < 3; k++) {
222 Msg::Debug(
"Boundary layer manager computes extruded elements in region %d",
228 for(
size_t i = 0; i <
edges.size(); i++) {
229 GFace *
f[2] = {
nullptr,
nullptr};
233 for(
size_t j = 0; j <
efaces.size(); j++) {
245 for(
size_t j = 0; j <
edges[i]->lines.size(); j++) {
246 for(
int k = 0; k < 2; k++) {
261 for(
size_t i = 0; i < bls.size(); i++) {
262 for(
size_t j = 0; j < bls[i]->triangles.size(); j++) {
264 auto it = t_normals.find(t->
getFace(0));
266 if(it == t_normals.end())
270 for(
int k = 0; k < 3; k++) {
275 it->add_triangle(t, n, bls[i]);
283 for(
size_t i = 0; i <
_ridges.size(); i++) {
292 for(
size_t i = 0; i <
_ridges.size(); i++) {
296 _ridges[i].max_angle = -2 * M_PI;
297 _ridges[i].min_angle = 2 * M_PI;
298 for(
size_t j = 0; j < ge->
lines.size(); j++) {
305 for(
size_t k = 0; k < it->_triangles.size(); k++) {
306 MVertex *v0 = it->_triangles[k]->getVertex(0);
307 MVertex *v1 = it->_triangles[k]->getVertex(1);
308 MVertex *v2 = it->_triangles[k]->getVertex(2);
309 GFace *gf = it->_gfaces[k];
310 if((v0 == l0 && v1 == l1) || (v0 == l1 && v1 == l0)) {
311 if(gf == f0) { N[0] = it->_normals[k]; }
313 N[1] = it->_normals[k];
317 if((v0 == l0 && v2 == l1) || (v0 == l1 && v2 == l0)) {
318 if(gf == f0) { N[0] = it->_normals[k]; }
320 N[1] = it->_normals[k];
324 if((v1 == l0 && v2 == l1) || (v1 == l1 && v2 == l0)) {
325 if(gf == f0) { N[0] = it->_normals[k]; }
327 N[1] = it->_normals[k];
332 double alpha =
angle(N[0], N[1]);
335 0.5 * (l0->
y() + l1->
y()) - op1->
y(),
336 0.5 * (l0->
z() + l1->
z()) - op1->
z());
339 double sign =
dot(dir, N[0]);
340 if(sign < 0) alpha = -alpha;
368 std::vector<GFace *> _unique;
369 for(
size_t i = 0; i < v.
_gfaces.size(); i++) {
370 if(std::find(_unique.begin(), _unique.end(), v.
_gfaces[i]) ==
372 _unique.push_back(v.
_gfaces[i]);
376 for(
size_t i = 0; i < _unique.size(); i++) {
386 for(
size_t i = 0; i < _unique.size(); i++) {
387 for(
size_t j = i + 1; j < _unique.size(); j++) {
388 int num_subnormals = 0;
389 for(
size_t k = 0; k <
_ridges.size(); k++) {
390 if((
_ridges[k]._f[0] == _unique[i] &&
391 _ridges[k]._f[1] == _unique[j]) ||
392 (
_ridges[k]._f[1] == _unique[i] &&
393 _ridges[k]._f[0] == _unique[j])) {
394 num_subnormals =
_ridges[k].N_SUBNORMALS;
400 std::vector<MVertex *> fan;
401 for(
int k = 0; k < num_subnormals; k++) {
402 double u = (double)(k + 1) / (num_subnormals + 1);
403 SVector3 n = n0 * (1. - u) + n1 * u;
408 fan.push_back(new_v);
411 std::pair<GFace *, GFace *> pa = std::make_pair(_unique[i], _unique[j]);
419 std::vector<SPoint3> aaa;
429 std::vector<MLine *> plane_lines;
430 std::map<MVertex *, MVertex *> plane_vertices;
433 GFace *f0 = it->first.first;
434 GFace *f1 = it->first.second;
435 std::vector<MVertex *> &verts = it->second;
447 (p0.
y() - plane.
y) * plane.
plan[0][1] +
448 (p0.
z() - plane.
z) * plane.
plan[0][2],
449 (p0.
x() - plane.
x) * plane.
plan[1][0] +
450 (p0.
y() - plane.
y) * plane.
plan[1][1] +
451 (p0.
z() - plane.
z) * plane.
plan[1][2]);
453 (p1.
y() - plane.
y) * plane.
plan[0][1] +
454 (p1.
z() - plane.
z) * plane.
plan[0][2],
455 (p1.
x() - plane.
x) * plane.
plan[1][0] +
456 (p1.
y() - plane.
y) * plane.
plan[1][1] +
457 (p1.
z() - plane.
z) * plane.
plan[1][2]);
460 auto itp = plane_vertices.find(v0);
461 if(itp != plane_vertices.end())
462 v_plane_0 = itp->second;
465 plane_vertices[v0] = v_plane_0;
468 itp = plane_vertices.find(v1);
469 if(itp != plane_vertices.end())
470 v_plane_1 = itp->second;
473 plane_vertices[v1] = v_plane_1;
476 for(
size_t i = 0; i < verts.size(); i++) {
481 (pp.
y() - plane.
y) * plane.
plan[0][1] +
482 (pp.
z() - plane.
z) * plane.
plan[0][2],
483 (pp.
x() - plane.
x) * plane.
plan[1][0] +
484 (pp.
y() - plane.
y) * plane.
plan[1][1] +
485 (pp.
z() - plane.
z) * plane.
plan[1][2]);
487 plane_vertices[vv] = v_plane;
489 plane_lines.push_back(
new MLine(v_plane_0, v_plane));
490 else if(i == verts.size() - 1) {
491 plane_lines.push_back(
new MLine(
492 plane_lines[plane_lines.size() - 1]->getVertex(1), v_plane));
493 plane_lines.push_back(
new MLine(v_plane, v_plane_1));
496 MVertex *vV = plane_lines[plane_lines.size() - 1]->getVertex(1);
497 plane_lines.push_back(
new MLine(vV, v_plane));
502 std::vector<MTriangle *> mesh;
503 std::vector<MVertex *> new_vertices;
506 for(
size_t i = 0; i < new_vertices.size(); i++) {
509 plane.
x + plane.
plan[0][0] * vv->
x() + plane.
plan[1][0] * vv->
y(),
510 plane.
y + plane.
plan[0][1] * vv->
x() + plane.
plan[1][1] * vv->
y(),
511 plane.
z + plane.
plan[0][2] * vv->
x() + plane.
plan[1][2] * vv->
y());
520 plane_vertices[newv] = vv;
523 std::map<int, MVertex *> plane_vertices_inv;
524 for(
auto it = plane_vertices.begin(); it != plane_vertices.end(); ++it)
525 plane_vertices_inv[it->second->getNum()] = it->first;
528 for(
size_t i = 0; i < mesh.size(); i++) {
529 MVertex *v0 = plane_vertices_inv[mesh[i]->getVertex(0)->getNum()];
530 MVertex *v1 = plane_vertices_inv[mesh[i]->getVertex(1)->getNum()];
531 MVertex *v2 = plane_vertices_inv[mesh[i]->getVertex(2)->getNum()];
537 for(
size_t i = 0; i < new_vertices.size(); i++)
delete new_vertices[i];
556 std::vector<blyr_mvertex> &new_vertices)
563 v.
_v->
y() + t * sqrt(2.0) * n.
y(),
564 v.
_v->
z() + t * sqrt(2.0) * n.
z());
568 for(
int i = 0; i < 2; i++) {
570 GFace *f_other = ridge->
_f[(i + 1) % 2];
573 v.
_v->
z() + t * n.
z());
574 double initialGuess[2] = {0, 0};
575 GPoint p =
f->closestPoint(newp, initialGuess);
577 f->mesh_vertices.push_back(vs[i]);
582 for(
size_t j = 0; j < v.
_triangles.size(); j++) {
584 for(
int k = 0; k < 3; k++)
593 new_vertices.push_back(bv);
595 std::pair<GFace *, GFace *> pa = std::make_pair(ridge->
_f[0], ridge->
_f[1]);
596 std::vector<MVertex *> fan;
607 for(
size_t i = 0; i <
_ridges.size(); i++) {
612 for(
size_t j = 0; j < r.
_ge->
lines.size(); j++) {
619 MVertex *o00 = it0->extruded_vertex(f0);
620 MVertex *o01 = it0->extruded_vertex(f1);
621 MVertex *o10 = it1->extruded_vertex(f0);
622 MVertex *o11 = it1->extruded_vertex(f1);
634 std::vector<blyr_mvertex> new_vertices;
639 if(it->_lines.size() == 2) {
640 GEdge *ge0 = it->_gedges[0];
641 GEdge *ge1 = it->_gedges[1];
644 if(ridge0 ==
nullptr && ridge1 ==
nullptr)
648 if(ridge0 == ridge1) {
654 "there is a seam... and we should extrude on that seam");
661 _vertices.insert(new_vertices.begin(), new_vertices.end());
666 std::vector<blyr_mvertex> vplus;
669 if(it->_lines.size() > 2) {
670 std::vector<blyr_ridge *> _internals;
671 std::vector<blyr_ridge *> _externals;
672 std::vector<MVertex *> _externals_v;
673 std::vector<MVertex *> _internals_v;
674 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
675 GEdge *ge = it->_gedges[iGe];
676 MLine *ml = it->_lines[iGe];
681 _externals.push_back(ridge);
682 _externals_v.push_back(o);
685 _internals.push_back(ridge);
686 _internals_v.push_back(o);
689 size_t nINTERNAL = _internals.size();
690 size_t nEXTERNAL = _externals.size();
694 if(nINTERNAL == (it->_gedges.size() - 1) && nEXTERNAL == 1) {
701 double initialGuess[2] = {0, 0};
703 printf(
"average normals --> %d %d\n", ridge->
_f[0]->
tag(),
704 ridge->
_f[1]->
tag());
705 SVector3 n1 = it->average_normal(ridge->
_f[0]);
706 SVector3 n2 = it->average_normal(ridge->
_f[1]);
707 double thk =
blyr_thickness(it->_v->x(), it->_v->y(), it->_v->z());
709 printf(
"%g %g %g -- %g %g %g\n", n1.
x(), n1.
y(), n1.
z(), n2.
x(),
711 SPoint3 p(it->_v->x() + n.
x(), it->_v->y() + n.
y(),
712 it->_v->z() + n.
z());
714 for(
size_t k = 0; k < it->_gfaces.size(); k++) {
715 std::vector<GEdge *> e = it->_gfaces[k]->
edges();
716 if(std::find(e.begin(), e.end(), ridge->
_ge) == e.end()) {
722 Msg::Error(
"Topological error in 3D boundary layer generation");
724 printf(
"adding a point %g %g %g in face %d\n", n.
x(), n.
y(), n.
z(),
730 for(
size_t j = 0; j < it->_triangles.size(); j++) {
734 blv.
_normals.push_back(it->_normals[j]);
735 if(it->_gfaces[j] == gf) {
736 for(
int k = 0; k < 3; k++) {
747 std::vector<MVertex *> fan;
748 fan.push_back(ite->_v_per_face[0]);
750 it->_v_per_face.push_back(vf);
751 it->_n_per_vertex.push_back(n);
752 it->_f_per_normal.push_back(gf);
753 it->_v_per_face.push_back(ite->_v);
754 it->_n_per_vertex.push_back(n);
755 it->_f_per_normal.push_back(_externals[0]->_f[0]);
756 it->_v_per_face.push_back(ite->_v);
757 it->_n_per_vertex.push_back(n);
758 it->_f_per_normal.push_back(_externals[0]->_f[1]);
760 for(
size_t k = 0; k < _internals.size(); k++) {
761 std::pair<GFace *, GFace *> pa =
762 std::make_pair(_internals[k]->_f[0], _internals[k]->_f[1]);
763 it->_v_per_ridge[pa] = fan;
765 MVertex *o = iti->_v_per_face[0];
768 if(_externals[0]->_f[0] == _internals[k]->_f[0] ||
769 _externals[0]->_f[0] == _internals[k]->_f[1]) {
770 MVertex *l = iti->extruded_vertex(_externals[0]->_f[0]);
771 _externals[0]->_f[0]->quadrangles.push_back(
774 else if(_externals[0]->_f[1] == _internals[k]->_f[0] ||
775 _externals[0]->_f[1] == _internals[k]->_f[1]) {
776 MVertex *l = iti->extruded_vertex(_externals[0]->_f[1]);
777 _externals[0]->_f[1]->quadrangles.push_back(
783 vplus.push_back(blv);
787 for(
size_t i = 0; i < vplus.size(); i++)
788 if(vplus[i]._v)
_vertices.insert(vplus[i]);
803 if(it->_lines.empty()) {
809 else if(it->_lines.size() == 2) {
812 GEdge *ge0 = it->_gedges[0];
813 GEdge *ge1 = it->_gedges[1];
819 if(ridge0 ==
nullptr && ridge1 ==
nullptr) {
836 std::vector<blyr_ridge *> _internals;
837 std::vector<blyr_ridge *> _externals;
838 std::vector<blyr_ridge *> _flats;
839 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
840 GEdge *ge = it->_gedges[iGe];
843 _externals.push_back(ridge);
845 _internals.push_back(ridge);
847 _flats.push_back(ridge);
849 size_t nINTERNAL = _internals.size();
850 size_t nEXTERNAL = _externals.size();
852 if(nEXTERNAL == it->_gedges.size()) {
859 else if(nINTERNAL == it->_gedges.size()) {
862 else if(nINTERNAL == 0 && nEXTERNAL == 0) {
866 else if(nINTERNAL == (it->_gedges.size() - 1) && nEXTERNAL == 1) {
870 Msg::Error(
"Corner with %d internal ridges and %d external ridges "
872 nINTERNAL, nEXTERNAL);
873 printf(
"EXTERNALS :");
874 for(
size_t i = 0; i < _externals.size(); i++)
875 printf(
"%d ", _externals[i]->_ge->tag());
877 printf(
"INTERNALS :");
878 for(
size_t i = 0; i < _internals.size(); i++)
879 printf(
"%d ", _internals[i]->_ge->tag());
897 std::vector<blyr_mvertex> additional_vertices;
903 std::map<GEdge *, MVertex *> e2v;
905 std::vector<blyr_ridge *> _internals;
906 std::vector<blyr_ridge *> _externals;
907 std::vector<blyr_ridge *> _flats;
908 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
909 GEdge *ge = it->_gedges[iGe];
912 _externals.push_back(ridge);
914 _internals.push_back(ridge);
916 _flats.push_back(ridge);
919 if(_internals.empty())
continue;
920 if(it->_lines.size() <= 2)
continue;
924 std::vector<blyr_mvertex> vplus;
925 std::vector<blyr_mvertex> vplusf;
926 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
927 GEdge *ge = it->_gedges[iGe];
930 bool create_vertices_on_edge =
932 if(create_vertices_on_edge) {
937 t = bounds.
low() + thk / tgt.
norm();
942 t = bounds.
high() - thk / tgt.
norm();
945 Msg::Error(
"Topological error in boundary layer");
952 SVector3(mev->
x() - v->
x(), mev->
y() - v->
y(), mev->
z() - v->
z());
961 if(_externals.empty()) {
968 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
969 if(vplus[iGe]._v !=
nullptr) {
970 GEdge *gei = it->_gedges[iGe];
973 for(
size_t jGe = 0; jGe < it->_gedges.size(); jGe++) {
975 GEdge *gej = it->_gedges[jGe];
983 SVector3 dx1(vplus[iGe]._v->x() - v->
x(),
984 vplus[iGe]._v->y() - v->
y(),
985 vplus[iGe]._v->z() - v->
z());
986 if((vplus[jGe]._v !=
nullptr) && (jGe > iGe)) {
987 SVector3 dx2(vplus[jGe]._v->x() - v->
x(),
988 vplus[jGe]._v->y() - v->
y(),
989 vplus[jGe]._v->z() - v->
z());
991 v->
y() + dx1.
y() + dx2.
y(),
992 v->
z() + dx1.
z() + dx2.
z());
997 !_internals.empty()) {
998 printf(
"ON VOLUME %d\n", gf->
tag());
1002 it->_n_per_vertex.push_back(dx1);
1003 it->_n_per_vertex.push_back(dx2);
1004 it->_v_per_face.push_back(vplus[iGe]._v);
1005 it->_v_per_face.push_back(vplus[jGe]._v);
1006 std::vector<GEdge *> e0 = _internals[0]->_f[0]->edges();
1007 if(std::find(e0.begin(), e0.end(), gei) != e0.end()) {
1008 it->_f_per_normal.push_back(_internals[0]->_f[0]);
1009 it->_f_per_normal.push_back(_internals[0]->_f[1]);
1012 it->_f_per_normal.push_back(_internals[0]->_f[1]);
1013 it->_f_per_normal.push_back(_internals[0]->_f[0]);
1015 std::vector<MVertex *> fan;
1017 std::pair<GFace *, GFace *> pa = std::make_pair(
1018 _internals[0]->_f[0], _internals[0]->_f[1]);
1019 it->_v_per_ridge[pa] = fan;
1021 vplus[iGe]._v_per_face.push_back(vf);
1022 vplus[jGe]._v_per_face.push_back(vf);
1023 vplus[iGe]._n_per_vertex.push_back(dx1);
1024 vplus[jGe]._n_per_vertex.push_back(dx2);
1025 vplus[iGe]._f_per_normal.push_back(_internals[0]->_f[0]);
1026 vplus[jGe]._f_per_normal.push_back(_internals[0]->_f[1]);
1029 double initialGuess[2];
1033 if(_externals.empty()) {
1038 vplusf.push_back(blv);
1043 new MQuadrangle(v, vplus[iGe]._v, vf, vplus[jGe]._v));
1047 vplus[iGe]._v_per_face.push_back(vf);
1048 vplus[jGe]._v_per_face.push_back(vf);
1049 vplus[iGe]._n_per_vertex.push_back(dx1);
1050 vplus[jGe]._n_per_vertex.push_back(dx2);
1051 vplus[iGe]._f_per_normal.push_back(gf);
1052 vplus[jGe]._f_per_normal.push_back(gf);
1055 else if(vplus[jGe]._v ==
nullptr) {
1065 if(!vf) printf(
"a bon\n");
1066 std::vector<MTriangle *> remaining_t;
1067 std::vector<GFace *> remaining_f;
1068 std::vector<SVector3> remaining_n;
1069 for(
size_t j = 0; j < it->_triangles.size(); j++) {
1071 if(it->_gfaces[j] == gf) {
1072 for(
int k = 0; k < 3; k++) {
1075 vplus[iGe]._triangles.push_back(t);
1076 vplus[iGe]._gfaces.push_back(it->_gfaces[j]);
1077 vplus[iGe]._normals.push_back(it->_normals[j]);
1080 remaining_t.push_back(t);
1081 remaining_f.push_back(it->_gfaces[j]);
1082 remaining_n.push_back(it->_normals[j]);
1093 std::vector<MVertex *> fan;
1095 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
1097 GEdge *gei = it->_gedges[iGe];
1099 std::pair<GFace *, GFace *> pa =
1100 std::make_pair(ridgei->
_f[0], ridgei->
_f[1]);
1101 vplus[iGe]._v_per_ridge[pa] = fan;
1106 std::vector<MLine *> update_lines;
1107 std::vector<GEdge *> update_gedges;
1109 for(
size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
1110 GEdge *ge = it->_gedges[iGe];
1111 MLine *ml = it->_lines[iGe];
1112 auto itev = e2v.find(ge);
1113 if(itev != e2v.end()) {
1120 update_lines.push_back(newl);
1121 update_gedges.push_back(ge);
1123 vplus[iGe]._lines.push_back(ml);
1124 vplus[iGe]._gedges.push_back(ge);
1125 vplus[iGe]._lines.push_back(newl);
1126 vplus[iGe]._gedges.push_back(ge);
1128 ge->
lines.push_back(newl);
1131 update_lines.push_back(ml);
1132 update_gedges.push_back(ge);
1140 it->_lines = update_lines;
1141 it->_gedges = update_gedges;
1142 for(
size_t i = 0; i < vplus.size(); i++)
1143 if(vplus[i]._v) additional_vertices.push_back(vplus[i]);
1145 additional_vertices.insert(additional_vertices.end(), vplusf.begin(),
1150 _vertices.insert(additional_vertices.begin(), additional_vertices.end());
1157 for(
size_t i = 0; i <
_faces.size(); i++) {
1158 for(
size_t j = 0; j <
_faces[i]->triangles.size(); j++) {
1178 for(
size_t i = 0; i <
_ridges.size(); i++) {
1182 std::pair<GFace *, GFace *> pa_pos = std::make_pair(f0, f1);
1183 std::pair<GFace *, GFace *> pa_neg = std::make_pair(f1, f0);
1188 for(
size_t j = 0; j < r.
_ge->
lines.size(); j++) {
1195 MVertex *o00 = it0->extruded_vertex(f0);
1196 MVertex *o01 = it0->extruded_vertex(f1);
1197 MVertex *o10 = it1->extruded_vertex(f0);
1198 MVertex *o11 = it1->extruded_vertex(f1);
1203 std::vector<MVertex *> fan0;
1204 std::vector<MVertex *> fan1;
1206 auto it = it0->_v_per_ridge.find(pa_pos);
1207 if(it != it0->_v_per_ridge.end())
1210 it = it0->_v_per_ridge.find(pa_neg);
1211 if(it != it0->_v_per_ridge.end()) {
1213 std::reverse(fan0.begin(), fan0.end());
1216 it = it1->_v_per_ridge.find(pa_pos);
1217 if(it != it1->_v_per_ridge.end())
1220 it = it1->_v_per_ridge.find(pa_neg);
1221 if(it != it1->_v_per_ridge.end()) {
1223 std::reverse(fan1.begin(), fan1.end());
1230 MVertex *v00 = (k == 0 ? o00 : fan0[k - 1]);
1231 MVertex *v10 = (k == 0 ? o10 : fan1[k - 1]);
1265 Msg::Info(
"Computing boundary layer mesh of volume %d", gr->
tag());
1279 Msg::Info(
"Classifying ridges (INTERNAL / EXTERNAL / FLAT)");
1281 Msg::Info(
"Extrusion of vertices for internal corners");
1283 Msg::Info(
"Extrusion of vertices for internal edges");
1289 Msg::Info(
"Treating corners with one external ridge and others internal");
1292 Msg::Info(
"Generating ONLE LAYER of 3D elements");