Lagrange
MeshNavigation.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/chain_corners_around_edges.h>
15#include <lagrange/chain_corners_around_vertices.h>
16#include <lagrange/corner_to_edge_mapping.h>
17
18#include <Eigen/Core>
19
20namespace lagrange {
21
29template <typename MeshType>
31{
32public:
33 using Scalar = typename MeshType::Scalar;
34 using Index = typename MeshType::Index;
35 using FacetArray = typename MeshType::FacetArray;
36 using IndexArray = Eigen::Matrix<Index, Eigen::Dynamic, 1>;
37
38public:
39 MeshNavigation(const MeshType& mesh) { initialize(mesh); }
40
41public:
47 Index get_num_edges() const { return safe_cast<Index>(m_e2c.size()); }
48
57 Index get_edge(Index f, Index lv) const { return m_c2e(f * m_vertex_per_facet + lv); }
58
68 Index get_edge_from_corner(Index c) const { return m_c2e(c); }
69
77 Index get_first_corner_around_edge(Index e) const { return m_e2c[e]; }
78
87 Index get_next_corner_around_edge(Index c) const { return m_next_corner_around_edge[c]; }
88
96 Index get_first_corner_around_vertex(Index v) const { return m_v2c[v]; }
97
107
116 std::array<Index, 2> get_edge_vertices(const FacetArray& facets, Index e) const
117 {
118 Index c = m_e2c[e];
119 if (c == invalid<Index>()) {
120 logger().error("Invalid corner id for edge {}", e);
121 throw std::runtime_error("Invalid edge id");
122 }
123 Index f = c / m_vertex_per_facet;
124 Index lv = c % m_vertex_per_facet;
125 return {{facets(f, lv), facets(f, (lv + 1) % m_vertex_per_facet)}};
126 }
127
138 Index get_vertex_opposite_edge(const FacetArray& facets, Index e) const
139 {
140 la_runtime_assert(m_vertex_per_facet == 3, "This method is only for triangle meshes.");
141 Index c = m_e2c[e];
142 if (c == invalid<Index>()) {
143 logger().error("Invalid corner id for edge {}", e);
144 throw std::runtime_error("Invalid edge id");
145 }
146 Index f = c / m_vertex_per_facet;
147 Index lv = c % m_vertex_per_facet;
148 return facets(f, (lv + 2) % m_vertex_per_facet);
149 }
150
157 Index get_num_facets_around_vertex(Index v) const
158 {
159 // Count number of incident facets
160 Index num_incident_facets = 0;
161 foreach_facets_around_vertex(v, [&](Index /*f*/) { ++num_incident_facets; });
162 return num_incident_facets;
163 }
164
171 Index get_num_facets_around_edge(Index e) const
172 {
173 // Count number of incident facets
174 Index num_incident_facets = 0;
175 foreach_facets_around_edge(e, [&](Index /*f*/) { ++num_incident_facets; });
176 return num_incident_facets;
177 }
178
186 Index get_one_facet_around_edge(Index e) const
187 {
188 Index c = m_e2c[e];
189 if (c != invalid<Index>()) {
190 return c / m_vertex_per_facet;
191 } else {
192 return invalid<Index>();
193 }
194 }
195
207 Index get_one_corner_around_edge(Index e) const { return m_e2c[e]; }
208
220 Index get_one_corner_around_vertex(Index v) const { return m_v2c[v]; }
221
229 bool is_boundary_edge(Index e) const
230 {
231 Index c = m_e2c[e];
232 assert(c != invalid<Index>());
233 return (m_next_corner_around_edge[c] == invalid<Index>());
234 }
235
243 bool is_boundary_vertex(Index v) const { return m_is_boundary_vertex[v]; }
244
245public:
254 template <typename Func>
255 void foreach_facets_around_vertex(Index v, Func func) const
256 {
257 // Loop over incident facets
258 for (Index c = m_v2c[v]; c != invalid<Index>(); c = m_next_corner_around_vertex[c]) {
259 Index f = c / m_vertex_per_facet;
260 func(f);
261 }
262 }
263
272 template <typename Func>
273 void foreach_facets_around_edge(Index e, Func func) const
274 {
275 // Loop over incident facets
276 for (Index c = m_e2c[e]; c != invalid<Index>(); c = m_next_corner_around_edge[c]) {
277 Index f = c / m_vertex_per_facet;
278 func(f);
279 }
280 }
281
290 template <typename Func>
291 void foreach_corners_around_vertex(Index v, Func func) const
292 {
293 // Loop over incident facets
294 for (Index c = m_v2c[v]; c != invalid<Index>(); c = m_next_corner_around_vertex[c]) {
295 func(c);
296 }
297 }
298
307 template <typename Func>
308 void foreach_corners_around_edge(Index e, Func func) const
309 {
310 // Loop over incident facets
311 for (Index c = m_e2c[e]; c != invalid<Index>(); c = m_next_corner_around_edge[c]) {
312 func(c);
313 }
314 }
315
316protected:
317 void initialize(const MeshType& mesh)
318 {
319 // Assumed to be constant
320 m_vertex_per_facet = mesh.get_vertex_per_facet();
321
322 // Compute unique edge ids
323 corner_to_edge_mapping(mesh.get_facets(), m_c2e);
324
325 // Chain corners around vertices and edges
328 mesh.get_num_vertices(),
329 mesh.get_facets(),
330 m_v2c,
332
333 // Tag boundary vertices
334 m_is_boundary_vertex.assign(mesh.get_num_vertices(), false);
335 for (Index e = 0; e < get_num_edges(); ++e) {
336 if (is_boundary_edge(e)) {
337 auto v = get_edge_vertices(mesh.get_facets(), e);
338 m_is_boundary_vertex[v[0]] = true;
339 m_is_boundary_vertex[v[1]] = true;
340 }
341 }
342 }
343
344protected:
346
347 IndexArray m_c2e;
348 IndexArray m_e2c;
350 IndexArray m_v2c;
352 std::vector<bool> m_is_boundary_vertex;
353};
354
355} // namespace lagrange
Definition: Mesh.h:48
This class is used to navigate elements of a mesh.
Definition: MeshNavigation.h:31
bool is_boundary_edge(Index e) const
Determines whether the specified edge e is a boundary edge.
Definition: MeshNavigation.h:229
IndexArray m_c2e
Corner to edge mapping.
Definition: MeshNavigation.h:347
bool is_boundary_vertex(Index v) const
Determines whether the specified vertex v is a boundary vertex.
Definition: MeshNavigation.h:243
Index get_num_facets_around_vertex(Index v) const
Count the number of facets incident to a given vertex.
Definition: MeshNavigation.h:157
Index get_one_corner_around_edge(Index e) const
Get the index of one corner around a given edge.
Definition: MeshNavigation.h:207
Index get_edge(Index f, Index lv) const
Gets the edge index corresponding to (f, lv) – (f, lv+1).
Definition: MeshNavigation.h:57
Index m_vertex_per_facet
Number of vertex per facet (assumed constant).
Definition: MeshNavigation.h:345
Index get_first_corner_around_edge(Index e) const
Get the index of the first corner around a given edge.
Definition: MeshNavigation.h:77
Index get_first_corner_around_vertex(Index v) const
Get the index of the first corner around a given vertex.
Definition: MeshNavigation.h:96
Index get_num_facets_around_edge(Index e) const
Count the number of facets incident to a given edge.
Definition: MeshNavigation.h:171
IndexArray m_v2c
Vertex to first corner in the chain.
Definition: MeshNavigation.h:350
IndexArray m_next_corner_around_vertex
Next corner in the chain around a vertex.
Definition: MeshNavigation.h:351
void foreach_facets_around_edge(Index e, Func func) const
Applies a function to each facet around a prescribed edge.
Definition: MeshNavigation.h:273
void foreach_corners_around_edge(Index e, Func func) const
Applies a function to each corner around a prescribed edge.
Definition: MeshNavigation.h:308
Index get_next_corner_around_vertex(Index c) const
Gets the next corner around the vertex associated to a corner.
Definition: MeshNavigation.h:106
Index get_one_facet_around_edge(Index e) const
Get the index of one facet around a given edge.
Definition: MeshNavigation.h:186
IndexArray m_e2c
Edge to first corner in the chain.
Definition: MeshNavigation.h:348
IndexArray m_next_corner_around_edge
Next corner in the chain around an edge.
Definition: MeshNavigation.h:349
Index get_one_corner_around_vertex(Index v) const
Get the index of one corner around a given vertex.
Definition: MeshNavigation.h:220
Index get_num_edges() const
Gets the number of edges.
Definition: MeshNavigation.h:47
Index get_vertex_opposite_edge(const FacetArray &facets, Index e) const
Returns a vertex id opposite the edge.
Definition: MeshNavigation.h:138
Index get_next_corner_around_edge(Index c) const
Gets the next corner around the edge associated to a corner.
Definition: MeshNavigation.h:87
void foreach_facets_around_vertex(Index v, Func func) const
Applies a function to each facet around a prescribed vertex.
Definition: MeshNavigation.h:255
void foreach_corners_around_vertex(Index v, Func func) const
Applies a function to each corner around a prescribed vertex.
Definition: MeshNavigation.h:291
Index get_edge_from_corner(Index c) const
Gets the edge index corresponding to a corner index.
Definition: MeshNavigation.h:68
std::array< Index, 2 > get_edge_vertices(const FacetArray &facets, Index e) const
Retrieve edge endpoints.
Definition: MeshNavigation.h:116
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition: Logger.cpp:40
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Eigen::Index corner_to_edge_mapping(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedC > &C2E)
Computes a mapping from mesh corners (k*f+i) to unique edge ids.
Definition: corner_to_edge_mapping.impl.h:31
void chain_corners_around_edges(const Eigen::MatrixBase< DerivedF > &facets, const Eigen::MatrixBase< DerivedC > &corner_to_edge, Eigen::PlainObjectBase< DerivedE > &edge_to_corner, Eigen::PlainObjectBase< DerivedN > &next_corner_around_edge)
Chains facet corners around edges of a mesh.
Definition: chain_corners_around_edges.h:39
void chain_corners_around_vertices(typename DerivedF::Scalar num_vertices, const Eigen::MatrixBase< DerivedF > &facets, Eigen::PlainObjectBase< DerivedE > &vertex_to_corner, Eigen::PlainObjectBase< DerivedN > &next_corner_around_vertex)
Chains facet corners around vertices of a mesh.
Definition: chain_corners_around_vertices.h:41