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>
42 std::vector<Index> inv(last - first, invalid<Index>());
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>
59 std::vector<Index> inv(last - first, invalid<Index>());
60 for (Index x = 0; x < Index(func.size()); ++x) {
61 const Index y = func[x];
62 if (y >= first && y < last) {
64 if (inv[y - first] != invalid<Index>() && inv[y - first] != x) {
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)
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));
123 seq_foreach_attribute_read<AttributeElement::Vertex>(mesh, [&](
auto&& attr) {
124 REQUIRE(attr.get_num_elements() == nv);
126 seq_foreach_attribute_read<AttributeElement::Facet>(mesh, [&](
auto&& attr) {
127 REQUIRE(attr.get_num_elements() == nf);
129 seq_foreach_attribute_read<AttributeElement::Corner>(mesh, [&](
auto&& attr) {
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));
187 REQUIRE(is_restriction_injective<Index>(
193 std::set<std::pair<Index, Index>> edges;
194 for (Index f = 0; f < nf; ++f) {
196 const Index lv1 = (lv0 + 1) % s;
199 edges.emplace(std::min(v0, v1), std::max(v0, v1));
202 std::vector<std::array<Index, 2>> mesh_edges;
203 for (Index e = 0; e < ne; ++e) {
205 mesh_edges.push_back({v[0], v[1]});
207 REQUIRE(edges.size() == e2c.size());
214 const Index lv0 = c - first_corner;
215 const Index lv1 = (lv0 + 1) % s;
218 edges.emplace(std::min(v0, v1), std::max(v0, v1));
220 REQUIRE(edges.size() == e2c.size());
223 for (Index f = 0; f < nf; ++f) {
227 const Index c = first_corner + lv0;
228 const Index e = c2e[c];
229 const Index c_other = e2c[e];
233 REQUIRE_THAT(mesh_edges[e], Catch::Matchers::Contains(v0));
234 REQUIRE_THAT(mesh_edges[e], Catch::Matchers::Contains(v_other));
239 std::vector<std::unordered_set<Index>> corners_around_vertex(nv);
240 std::vector<std::unordered_set<Index>> corners_around_edge(ne);
241 std::vector<std::unordered_set<Index>> facets_around_vertex(nv);
242 std::vector<std::unordered_set<Index>> facets_around_edge(ne);
243 for (Index f = 0; f < nf; ++f) {
247 const Index c = first_corner + lv;
248 const Index e = c2e[c];
251 REQUIRE(corners_around_vertex[v].count(c) == 0);
252 REQUIRE(corners_around_edge[e].count(c) == 0);
253 corners_around_vertex[v].insert(c);
254 corners_around_edge[e].insert(c);
255 facets_around_vertex[v].insert(f);
256 facets_around_edge[e].insert(f);
259 std::unordered_set<Index> corners_around;
260 std::unordered_set<Index> facets_around;
261 for (Index v = 0; v < nv; ++v) {
262 corners_around.clear();
263 facets_around.clear();
264 const Index c0 = v2c[v];
267 for (Index ci = c0; ci != invalid<Index>(); ci = next_around_vertex[ci]) {
269 REQUIRE(corners_around_vertex[v].count(ci));
270 REQUIRE(corners_around.count(ci) == 0);
271 corners_around.insert(ci);
274 REQUIRE(corners_around.count(c));
277 REQUIRE(facets_around_vertex[v].count(f));
278 facets_around.insert(f);
280 REQUIRE(corners_around.size() == corners_around_vertex[v].size());
281 REQUIRE(facets_around.size() == facets_around_vertex[v].size());
283 corners_around.size() ==
286 for (Index e = 0; e < ne; ++e) {
287 corners_around.clear();
288 facets_around.clear();
289 const Index c0 = e2c[e];
292 for (Index ci = c0; ci != invalid<Index>(); ci = next_around_edge[ci]) {
294 REQUIRE(corners_around_edge[e].count(ci));
295 REQUIRE(corners_around.count(ci) == 0);
296 corners_around.insert(ci);
299 Index first_facet = invalid<Index>();
301 REQUIRE(facets_around_edge[e].count(f));
302 facets_around.insert(f);
303 if (first_facet == invalid<Index>()) {
308 REQUIRE(corners_around.size() == corners_around_edge[e].size());
309 REQUIRE(facets_around.size() == facets_around_edge[e].size());
313 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:2664
bool is_boundary_edge(Index e) const
Determines whether the specified edge e is a boundary edge.
Definition: SurfaceMesh.cpp:2615
Index get_facet_corner_end(Index f) const
Index past the last corner around the facet.
Definition: SurfaceMesh.cpp:2151
AttributeId attr_id_corner_to_edge() const
Attribute id for corner -> edge indices.
Definition: SurfaceMesh.h:2070
Index count_num_corners_around_edge(Index e) const
Count the number of corners incident to a given edge.
Definition: SurfaceMesh.cpp:2586
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:2443
AttributeId attr_id_facet_to_first_corner() const
Attribute id for facet -> first corner index.
Definition: SurfaceMesh.h:2053
std::array< Index, 2 > get_edge_vertices(Index e) const
Retrieve edge endpoints.
Definition: SurfaceMesh.cpp:2457
Index get_edge(Index f, Index lv) const
Gets the edge index corresponding to (f, lv) – (f, lv+1).
Definition: SurfaceMesh.cpp:2435
Index get_next_corner_around_edge(Index c) const
Gets the next corner around the edge associated to a corner.
Definition: SurfaceMesh.cpp:2514
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:2641
Index count_num_corners_around_vertex(Index v) const
Count the number of corners incident to a given vertex.
Definition: SurfaceMesh.cpp:2532
Index get_one_corner_around_vertex(Index v) const
Get the index of one corner around a given vertex.
Definition: SurfaceMesh.cpp:2609
Index get_facet_corner_begin(Index f) const
First corner around the facet.
Definition: SurfaceMesh.cpp:2139
AttributeId attr_id_vertex_to_first_corner() const
Attribute id for vertex -> first corner index.
Definition: SurfaceMesh.h:2097
Index get_one_facet_around_edge(Index e) const
Get the index of one facet around a given edge.
Definition: SurfaceMesh.cpp:2595
Index get_first_corner_around_edge(Index e) const
Get the index of the first corner around a given edge.
Definition: SurfaceMesh.cpp:2508
bool is_regular() const
Whether the mesh must only contains facets of equal sizes.
Definition: SurfaceMesh.cpp:2104
AttributeId attr_id_next_corner_around_edge() const
Attribute id for corner -> next corner around edge.
Definition: SurfaceMesh.h:2087
Index get_first_corner_around_vertex(Index v) const
Get the index of the first corner around a given vertex.
Definition: SurfaceMesh.cpp:2520
Index get_next_corner_around_vertex(Index c) const
Gets the next corner around the vertex associated to a corner.
Definition: SurfaceMesh.cpp:2526
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:2165
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:2686
Index get_corner_facet(Index c) const
Retrieves the index of a facet given its corner index.
Definition: SurfaceMesh.cpp:2171
bool has_edges() const
Determines if the attributes associated to mesh edges and connectivity have been initialized.
Definition: SurfaceMesh.h:2159
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:2603
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:2077
AttributeId attr_id_next_corner_around_vertex() const
Attribute id for corner -> next corner around vertex.
Definition: SurfaceMesh.h:2107
AttributeId attr_id_corner_to_facet() const
Attribute id for corner -> facet index.
Definition: SurfaceMesh.h:2063
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:2700
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.
@ VertexIndex
Single channel integer attribute indexing a mesh vertex.
@ EdgeIndex
Single channel integer attribute indexing a mesh edge.
@ FacetIndex
Single channel integer attribute indexing a mesh facet.
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
#define LA_IGNORE(x)
Ignore x to avoid an unused variable warning.
Definition: warning.h:144
Main namespace for Lagrange.
Definition: AABBIGL.h:30