Lagrange
Loading...
Searching...
No Matches
check_meshes_equal.h
1/*
2 * Copyright 2026 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
13#pragma once
14
15#include <lagrange/Attribute.h>
16#include <lagrange/IndexedAttribute.h>
17#include <lagrange/SurfaceMesh.h>
18#include <lagrange/foreach_attribute.h>
19
20// clang-format off
21#include <lagrange/utils/warnoff.h>
22#include <catch2/catch_test_macros.hpp>
23#include <lagrange/utils/warnon.h>
24// clang-format on
25
26#include <string>
27#include <vector>
28
29namespace lagrange::testing {
30
44template <typename Scalar, typename Index>
45void check_meshes_equal(const SurfaceMesh<Scalar, Index>& a, const SurfaceMesh<Scalar, Index>& b)
46{
47 // Check topology counts
48 REQUIRE(a.get_num_vertices() == b.get_num_vertices());
49 REQUIRE(a.get_num_facets() == b.get_num_facets());
50 REQUIRE(a.get_num_corners() == b.get_num_corners());
51 REQUIRE(a.get_num_edges() == b.get_num_edges());
52 REQUIRE(a.get_dimension() == b.get_dimension());
53
54 if (a.is_regular()) {
55 REQUIRE(b.is_regular());
57 } else {
58 REQUIRE(b.is_hybrid());
59 }
60
61 // Collect all attribute names from both meshes
62 std::vector<std::pair<std::string, AttributeId>> names_a, names_b;
63 a.seq_foreach_attribute_id([&](std::string_view name, AttributeId id) {
64 names_a.emplace_back(std::string(name), id);
65 });
66 b.seq_foreach_attribute_id([&](std::string_view name, AttributeId id) {
67 names_b.emplace_back(std::string(name), id);
68 });
69
70 // Check that all attributes in a exist in b
71 for (const auto& [name, id] : names_a) {
72 INFO("Attribute in a missing from b: " << name);
73 REQUIRE(b.has_attribute(name));
74 }
75
76 // Check that all attributes in b exist in a
77 for (const auto& [name, id] : names_b) {
78 INFO("Attribute in b missing from a: " << name);
79 REQUIRE(a.has_attribute(name));
80 }
81
82 // Check that user attribute IDs match
83 for (const auto& [name, id_a] : names_a) {
85 INFO("Checking attribute id for: " << name);
86 REQUIRE(b.get_attribute_id(name) == id_a);
87 }
88
89 // Check all attribute data (reserved and non-reserved)
90 seq_foreach_named_attribute_read(a, [&](std::string_view name, auto&& attr_a) {
91 using AttrType = std::decay_t<decltype(attr_a)>;
92
93 INFO("Checking attribute data: " << std::string(name));
94 REQUIRE(b.has_attribute(name));
95
96 if constexpr (AttrType::IsIndexed) {
97 using ValueType = typename AttrType::ValueType;
98 const auto& attr_b = b.template get_indexed_attribute<ValueType>(name);
99 auto vals_a = attr_a.values().get_all();
100 auto vals_b = attr_b.values().get_all();
101 REQUIRE(vals_a.size() == vals_b.size());
102 for (size_t i = 0; i < vals_a.size(); ++i) {
103 REQUIRE(vals_a[i] == vals_b[i]);
104 }
105 auto idx_a = attr_a.indices().get_all();
106 auto idx_b = attr_b.indices().get_all();
107 REQUIRE(idx_a.size() == idx_b.size());
108 for (size_t i = 0; i < idx_a.size(); ++i) {
109 REQUIRE(idx_a[i] == idx_b[i]);
110 }
111 } else {
112 using ValueType = typename AttrType::ValueType;
113 const auto& attr_b = b.template get_attribute<ValueType>(name);
114 REQUIRE(attr_a.get_num_elements() == attr_b.get_num_elements());
115 REQUIRE(attr_a.get_num_channels() == attr_b.get_num_channels());
116 auto span_a = attr_a.get_all();
117 auto span_b = attr_b.get_all();
118 REQUIRE(span_a.size() == span_b.size());
119 for (size_t i = 0; i < span_a.size(); ++i) {
120 REQUIRE(span_a[i] == span_b[i]);
121 }
122 }
123 });
124}
125
126} // namespace lagrange::testing
Index get_num_vertices() const
Retrieves the number of vertices.
Definition SurfaceMesh.h:687
Index get_dimension() const
Retrieves the dimension of the mesh vertices.
Definition SurfaceMesh.h:672
AttributeId get_attribute_id(std::string_view name) const
Retrieve an attribute id given its name.
Definition SurfaceMesh.cpp:347
bool has_attribute(std::string_view name) const
Checks if an attribute of a given name is attached to the mesh.
Definition SurfaceMesh.cpp:1216
bool is_regular() const
Whether the mesh must only contains facets of equal sizes.
Definition SurfaceMesh.cpp:2332
bool is_hybrid() const
Whether the mesh may contain facets of different sizes.
Definition SurfaceMesh.h:665
Index get_num_edges() const
Retrieves the number of edges.
Definition SurfaceMesh.h:708
Index get_num_facets() const
Retrieves the number of facets.
Definition SurfaceMesh.h:694
Index get_vertex_per_facet() const
Retrieves the number of vertex per facet in a regular mesh.
Definition SurfaceMesh.cpp:2346
static bool attr_name_is_reserved(std::string_view name)
Index get_num_corners() const
Retrieves the number of corners.
Definition SurfaceMesh.h:701
void seq_foreach_attribute_id(function_ref< void(AttributeId)> func) const
Iterates over all attribute ids sequentially.
Definition SurfaceMesh.cpp:1250
uint32_t AttributeId
Identified to be used to access an attribute.
Definition AttributeFwd.h:73
void seq_foreach_named_attribute_read(const SurfaceMesh< Scalar, Index > &mesh, Visitor &&vis)
Applies a function to each attribute of a mesh.
Definition foreach_attribute.h:208