PolyFEM
Loading...
Searching...
No Matches
Navigation.cpp
Go to the documentation of this file.
1
3
5
6#include <algorithm>
7#include <cassert>
9
10using namespace GEO;
11using namespace polyfem::mesh::Navigation;
12
13namespace
14{
15
16 typedef std::pair<index_t, index_t> Edge;
17
18 Edge make_edge(index_t v1, index_t v2)
19 {
20 return std::make_pair(std::min(v1, v2), std::max(v1, v2));
21 }
22
23} // anonymous namespace
24
25// -----------------------------------------------------------------------------
26
28{
29 M.facets.connect();
30 M.cells.connect();
31 if (M.cells.nb() != 0 && M.facets.nb() == 0)
32 {
33 M.cells.compute_borders();
34 }
35
36 // Compute a list of all the edges, and store edge index as a corner attribute
37 std::vector<std::pair<Edge, index_t>> e2c; // edge to corner id
38 for (index_t f = 0; f < M.facets.nb(); ++f)
39 {
40 for (index_t c = M.facets.corners_begin(f); c < M.facets.corners_end(f); ++c)
41 {
42 index_t v = M.facet_corners.vertex(c);
43 index_t c2 = M.facets.next_corner_around_facet(f, c);
44 index_t v2 = M.facet_corners.vertex(c2);
45 e2c.emplace_back(make_edge(v, v2), c);
46 }
47 }
48 std::sort(e2c.begin(), e2c.end());
49
50 // Assign unique id to edges
51 GEO::Attribute<index_t> c2e(M.facet_corners.attributes(), "edge_id");
52 M.edges.clear();
53 Edge prev_e(-1, -1);
54 index_t current_id = -1;
55 std::vector<bool> boundary_edges;
56 for (const auto &kv : e2c)
57 {
58 Edge e = kv.first;
59 index_t c = kv.second;
60 if (e != prev_e)
61 {
62 M.edges.create_edge(e.first, e.second);
63 boundary_edges.push_back(true);
64 ++current_id;
65 prev_e = e;
66 }
67 else
68 {
69 boundary_edges.back() = false;
70 }
71 c2e[c] = current_id;
72 }
73
74 GEO::Attribute<bool> boundary_edges_attr(M.edges.attributes(), "boundary_edge");
75 assert(M.edges.nb() == (index_t)boundary_edges.size());
76 for (index_t e = 0; e < M.edges.nb(); ++e)
77 {
78 boundary_edges_attr[e] = boundary_edges[e] ? 1 : 0;
79 }
80
81 GEO::Attribute<bool> boundary_vertices(M.vertices.attributes(), "boundary_vertex");
82 boundary_vertices.fill(0);
83 for (index_t e = 0; e < M.edges.nb(); ++e)
84 {
85 if (boundary_edges[e])
86 {
87 boundary_vertices[M.edges.vertex(e, 0)] = 1;
88 boundary_vertices[M.edges.vertex(e, 1)] = 1;
89 }
90 }
91}
92
93// -----------------------------------------------------------------------------
94
95// Retrieve the index (v,e,f) of one vertex incident to the given face
96Index polyfem::mesh::Navigation::get_index_from_face(const GEO::Mesh &M, const GEO::Attribute<GEO::index_t> &c2e, int f, int lv)
97{
98 // GEO::Attribute<index_t> c2e(M.facet_corners.attributes(), "edge_id");
99 Index idx;
100 idx.face_corner = M.facets.corner(f, lv);
101 idx.vertex = M.facet_corners.vertex(idx.face_corner);
102 idx.face = f;
103 idx.edge = c2e[idx.face_corner];
104 int v2 = int(M.facets.vertex(f, (lv + 1) % M.facets.nb_vertices(f)));
105 if (switch_vertex(M, idx).vertex != v2)
106 {
107 assert(false);
108 return switch_edge(M, c2e, idx);
109 }
110 return idx;
111}
112
114
116{
117 index_t c1 = M.facets.next_corner_around_facet(idx.face, idx.face_corner);
118 index_t v1 = M.facet_corners.vertex(c1);
119 if (v1 == M.edges.vertex(idx.edge, 0) || v1 == M.edges.vertex(idx.edge, 1))
120 {
121 idx.face_corner = c1;
122 idx.vertex = v1;
123 return idx;
124 }
125 else
126 {
127 index_t c2 = M.facets.prev_corner_around_facet(idx.face, idx.face_corner);
128 index_t v2 = M.facet_corners.vertex(c2);
129 assert(v2 == M.edges.vertex(idx.edge, 0) || v2 == M.edges.vertex(idx.edge, 1));
130 idx.face_corner = c2;
131 idx.vertex = v2;
132 return idx;
133 }
134}
135
136Index polyfem::mesh::Navigation::switch_edge(const GEO::Mesh &M, const GEO::Attribute<GEO::index_t> &c2e, Index idx)
137{
138 index_t v2 = M.edges.vertex(idx.edge, 0);
139 if (v2 == (index_t)idx.vertex)
140 {
141 v2 = M.edges.vertex(idx.edge, 1);
142 }
143 // GEO::Attribute<index_t> c2e(M.facet_corners.attributes(), "edge_id");
144 index_t c1 = M.facets.next_corner_around_facet(idx.face, idx.face_corner);
145 index_t v1 = M.facet_corners.vertex(c1);
146 if (v1 == v2)
147 {
148 index_t c2 = M.facets.prev_corner_around_facet(idx.face, idx.face_corner);
149 idx.edge = c2e[c2];
150 return idx;
151 }
152 else
153 {
154 idx.edge = c2e[idx.face_corner];
155 return idx;
156 }
157}
158
159Index polyfem::mesh::Navigation::switch_face(const GEO::Mesh &M, const GEO::Attribute<GEO::index_t> &c2e, Index idx)
160{
161 // GEO::Attribute<index_t> c2e(M.facet_corners.attributes(), "edge_id");
162 index_t c1 = idx.face_corner;
163 if (c2e[c1] != (index_t)idx.edge)
164 {
165 c1 = M.facets.prev_corner_around_facet(idx.face, c1);
166 }
167 index_t f2 = M.facet_corners.adjacent_facet(c1);
168 if (f2 == NO_FACET)
169 {
170 // std::cout << "No facet" << std::endl;
171 idx.face = -1;
172 return idx;
173 }
174 else
175 {
176 // Iterate over all corners of the new face until we find the vertex we came from.
177 // Not ideal but for now it will do the job.
178 for (index_t c2 = M.facets.corners_begin(f2); c2 < M.facets.corners_end(f2); ++c2)
179 {
180 index_t v2 = M.facet_corners.vertex(c2);
181 if (v2 == (index_t)idx.vertex)
182 {
183 idx.face = f2;
184 idx.face_corner = c2;
185 return idx;
186 }
187 }
188 logger().error("Not found");
189 assert(false); // This should not happen
190 return idx;
191 }
192}
Index get_index_from_face(const GEO::Mesh &M, const GEO::Attribute< GEO::index_t > &c2e, int f, int lv)
Index switch_face(const GEO::Mesh &M, const GEO::Attribute< GEO::index_t > &c2e, Index idx)
Index switch_edge(const GEO::Mesh &M, const GEO::Attribute< GEO::index_t > &c2e, Index idx)
void prepare_mesh(GEO::Mesh &M)
Index switch_vertex(const GEO::Mesh &M, Index idx)
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:42