15#include <lagrange/SurfaceMesh.h>
16#include <lagrange/foreach_attribute.h>
17#include <lagrange/utils/invalid.h>
18#include <lagrange/utils/safe_cast.h>
21#include <lagrange/utils/warnoff.h>
22#include <catch2/catch_test_macros.hpp>
23#include <catch2/matchers/catch_matchers_contains.hpp>
24#include <lagrange/utils/warnon.h>
31#include <unordered_set>
34namespace lagrange::testing {
38template <
typename Index>
41 using namespace lagrange;
43 for (Index x = 0; x < Index(func.size()); ++x) {
44 const Index y = func[x];
45 if (y >= first && y < last) {
50 return std::none_of(inv.begin(), inv.end(), [&](Index y) { return y == invalid<Index>(); });
55template <
typename Index>
58 using namespace lagrange;
60 for (Index x = 0; x < Index(func.size()); ++x) {
61 const Index y = func[x];
62 if (y >= first && y < last) {
74template <
typename Index>
77 return std::all_of(func.begin(), func.end(), [&](Index y) { return first <= y && y < last; });
80template <
typename Index>
83 return std::all_of(func.begin(), func.end(), [&](Index y) {
84 return (first <= y && y < last) || y == lagrange::invalid<Index>();
88template <
typename Index>
91 return is_in_range(func, first, last) && is_restriction_surjective(func, first, last);
94template <
typename Index>
97 return is_in_range(func, first, last) && is_restriction_injective(func, first, last);
100template <
typename MeshType>
101void check_mesh(
const MeshType& mesh)
103 using namespace lagrange;
104 using Index =
typename MeshType::Index;
111 for (Index f = 0; f < nf; ++f) {
115 for (Index c = c0; c < c1; ++c) {
118 REQUIRE((v >= 0 && v < nv));
124 REQUIRE(attr.get_num_elements() == nv);
127 REQUIRE(attr.get_num_elements() == nf);
130 REQUIRE(attr.get_num_elements() == nc);
135 using AttributeType = std::decay_t<
decltype(attr)>;
136 using ValueType =
typename AttributeType::ValueType;
138 auto usage = attr.get_usage();
150 REQUIRE(std::is_same_v<ValueType, Index>);
151 if constexpr (std::is_same_v<ValueType, Index>) {
152 if constexpr (AttributeType::IsIndexed) {
153 REQUIRE(is_in_range_or_invalid<ValueType>(attr.values().get_all(), 0, n));
155 REQUIRE(is_in_range_or_invalid<ValueType>(attr.get_all(), 0, n));
180 auto next_around_edge =
182 auto next_around_vertex =
184 REQUIRE(is_surjective<Index>(c2e, 0, ne));
185 REQUIRE(is_injective<Index>(e2c, 0, nc));
186 REQUIRE(is_in_range_or_invalid<Index>(v2c, 0, nc));
188 is_restriction_injective<Index>(
194 std::set<std::pair<Index, Index>> edges;
195 for (Index f = 0; f < nf; ++f) {
197 const Index lv1 = (lv0 + 1) % s;
200 edges.emplace(std::min(v0, v1), std::max(v0, v1));
203 std::vector<std::array<Index, 2>> mesh_edges;
204 for (Index e = 0; e < ne; ++e) {
206 mesh_edges.push_back({v[0], v[1]});
208 REQUIRE(edges.size() == e2c.size());
215 const Index lv0 = c - first_corner;
216 const Index lv1 = (lv0 + 1) % s;
219 edges.emplace(std::min(v0, v1), std::max(v0, v1));
221 REQUIRE(edges.size() == e2c.size());
224 for (Index f = 0; f < nf; ++f) {
228 const Index c = first_corner + lv0;
229 const Index e = c2e[c];
230 const Index c_other = e2c[e];
234 REQUIRE_THAT(mesh_edges[e], Catch::Matchers::Contains(v0));
235 REQUIRE_THAT(mesh_edges[e], Catch::Matchers::Contains(v_other));
240 std::vector<std::unordered_set<Index>> corners_around_vertex(nv);
241 std::vector<std::unordered_set<Index>> corners_around_edge(ne);
242 std::vector<std::unordered_set<Index>> facets_around_vertex(nv);
243 std::vector<std::unordered_set<Index>> facets_around_edge(ne);
244 for (Index f = 0; f < nf; ++f) {
248 const Index c = first_corner + lv;
249 const Index e = c2e[c];
252 REQUIRE(corners_around_vertex[v].count(c) == 0);
253 REQUIRE(corners_around_edge[e].count(c) == 0);
254 corners_around_vertex[v].insert(c);
255 corners_around_edge[e].insert(c);
256 facets_around_vertex[v].insert(f);
257 facets_around_edge[e].insert(f);
260 std::unordered_set<Index> corners_around;
261 std::unordered_set<Index> facets_around;
262 for (Index v = 0; v < nv; ++v) {
263 corners_around.clear();
264 facets_around.clear();
265 const Index c0 = v2c[v];
268 for (Index ci = c0; ci !=
invalid<Index>(); ci = next_around_vertex[ci]) {
270 REQUIRE(corners_around_vertex[v].count(ci));
271 REQUIRE(corners_around.count(ci) == 0);
272 corners_around.insert(ci);
275 REQUIRE(corners_around.count(c));
278 REQUIRE(facets_around_vertex[v].count(f));
279 facets_around.insert(f);
281 REQUIRE(corners_around.size() == corners_around_vertex[v].size());
282 REQUIRE(facets_around.size() == facets_around_vertex[v].size());
284 corners_around.size() ==
287 for (Index e = 0; e < ne; ++e) {
288 corners_around.clear();
289 facets_around.clear();
290 const Index c0 = e2c[e];
293 for (Index ci = c0; ci !=
invalid<Index>(); ci = next_around_edge[ci]) {
295 REQUIRE(corners_around_edge[e].count(ci));
296 REQUIRE(corners_around.count(ci) == 0);
297 corners_around.insert(ci);
302 REQUIRE(facets_around_edge[e].count(f));
303 facets_around.insert(f);
309 REQUIRE(corners_around.size() == corners_around_edge[e].size());
310 REQUIRE(facets_around.size() == facets_around_edge[e].size());
314 REQUIRE(corners_around.size() == 1);
void foreach_facet_around_edge(Index e, function_ref< void(Index)> func) const
Applies a function to each facet around a prescribed edge.
Definition SurfaceMesh.cpp:2670
bool is_boundary_edge(Index e) const
Determines whether the specified edge e is a boundary edge.
Definition SurfaceMesh.cpp:2621
Index get_facet_corner_end(Index f) const
Index past the last corner around the facet.
Definition SurfaceMesh.cpp:2157
AttributeId attr_id_corner_to_edge() const
Attribute id for corner -> edge indices.
Definition SurfaceMesh.h:2074
Index count_num_corners_around_edge(Index e) const
Count the number of corners incident to a given edge.
Definition SurfaceMesh.cpp:2592
Index get_num_vertices() const
Retrieves the number of vertices.
Definition SurfaceMesh.h:671
Index get_corner_edge(Index c) const
Gets the edge index corresponding to a corner index.
Definition SurfaceMesh.cpp:2449
AttributeId attr_id_facet_to_first_corner() const
Attribute id for facet -> first corner index.
Definition SurfaceMesh.h:2057
std::array< Index, 2 > get_edge_vertices(Index e) const
Retrieve edge endpoints.
Definition SurfaceMesh.cpp:2463
Index get_edge(Index f, Index lv) const
Gets the edge index corresponding to (f, lv) – (f, lv+1).
Definition SurfaceMesh.cpp:2441
Index get_next_corner_around_edge(Index c) const
Gets the next corner around the edge associated to a corner.
Definition SurfaceMesh.cpp:2520
void foreach_facet_around_vertex(Index v, function_ref< void(Index)> func) const
Applies a function to each facet around a prescribed vertex.
Definition SurfaceMesh.cpp:2647
Index count_num_corners_around_vertex(Index v) const
Count the number of corners incident to a given vertex.
Definition SurfaceMesh.cpp:2538
Index get_one_corner_around_vertex(Index v) const
Get the index of one corner around a given vertex.
Definition SurfaceMesh.cpp:2615
Index get_facet_corner_begin(Index f) const
First corner around the facet.
Definition SurfaceMesh.cpp:2145
AttributeId attr_id_vertex_to_first_corner() const
Attribute id for vertex -> first corner index.
Definition SurfaceMesh.h:2101
Index get_one_facet_around_edge(Index e) const
Get the index of one facet around a given edge.
Definition SurfaceMesh.cpp:2601
Index get_first_corner_around_edge(Index e) const
Get the index of the first corner around a given edge.
Definition SurfaceMesh.cpp:2514
bool is_regular() const
Whether the mesh must only contains facets of equal sizes.
Definition SurfaceMesh.cpp:2110
AttributeId attr_id_next_corner_around_edge() const
Attribute id for corner -> next corner around edge.
Definition SurfaceMesh.h:2091
Index get_first_corner_around_vertex(Index v) const
Get the index of the first corner around a given vertex.
Definition SurfaceMesh.cpp:2526
Index get_next_corner_around_vertex(Index c) const
Gets the next corner around the vertex associated to a corner.
Definition SurfaceMesh.cpp:2532
Index get_facet_vertex(Index f, Index lv) const
Index of a vertex given from a facet + local index.
Definition SurfaceMesh.h:732
Index get_corner_vertex(Index c) const
Retrieves the index of a vertex given its corner index.
Definition SurfaceMesh.cpp:2171
void foreach_corner_around_vertex(Index v, function_ref< void(Index)> func) const
Applies a function to each corner around a prescribed vertex.
Definition SurfaceMesh.cpp:2692
Index get_corner_facet(Index c) const
Retrieves the index of a facet given its corner index.
Definition SurfaceMesh.cpp:2177
bool has_edges() const
Determines if the attributes associated to mesh edges and connectivity have been initialized.
Definition SurfaceMesh.h:2163
bool is_hybrid() const
Whether the mesh may contain facets of different sizes.
Definition SurfaceMesh.h:649
Index get_num_edges() const
Retrieves the number of edges.
Definition SurfaceMesh.h:692
Index get_one_corner_around_edge(Index e) const
Get the index of one corner around a given edge.
Definition SurfaceMesh.cpp:2609
Index get_num_facets() const
Retrieves the number of facets.
Definition SurfaceMesh.h:678
AttributeId attr_id_edge_to_first_corner() const
Attribute id for edge -> first corner index.
Definition SurfaceMesh.h:2081
AttributeId attr_id_next_corner_around_vertex() const
Attribute id for corner -> next corner around vertex.
Definition SurfaceMesh.h:2111
AttributeId attr_id_corner_to_facet() const
Attribute id for corner -> facet index.
Definition SurfaceMesh.h:2067
void foreach_corner_around_edge(Index e, function_ref< void(Index)> func) const
Applies a function to each corner around a prescribed edge.
Definition SurfaceMesh.cpp:2706
Index get_facet_size(Index f) const
Number of vertices in the facet.
Definition SurfaceMesh.h:719
Index get_num_corners() const
Retrieves the number of corners.
Definition SurfaceMesh.h:685
constexpr AttributeId invalid_attribute_id()
Invalid attribute id.
Definition AttributeFwd.h:76
@ CornerIndex
Single channel integer attribute indexing a mesh corner.
Definition AttributeFwd.h:65
@ VertexIndex
Single channel integer attribute indexing a mesh vertex.
Definition AttributeFwd.h:63
@ EdgeIndex
Single channel integer attribute indexing a mesh edge.
Definition AttributeFwd.h:66
@ FacetIndex
Single channel integer attribute indexing a mesh facet.
Definition AttributeFwd.h:64
void seq_foreach_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition foreach_attribute.h:233
::nonstd::span< T, Extent > span
A bounds-safe view for sequences of objects.
Definition span.h:27
constexpr T invalid()
You can use invalid<T>() to get a value that can represent "invalid" values, such as invalid indices ...
Definition invalid.h:40
constexpr auto safe_cast(SourceType value) -> std::enable_if_t<!std::is_same< SourceType, TargetType >::value, TargetType >
Perform safe cast from SourceType to TargetType, where "safe" means:
Definition safe_cast.h:50
#define LA_IGNORE(x)
Ignore x to avoid an unused variable warning.
Definition warning.h:144