14#include <lagrange/Edge.h>
15#include <lagrange/MeshTrait.h>
16#include <lagrange/legacy/inline.h>
17#include <lagrange/utils/assert.h>
18#include <lagrange/utils/range.h>
25#include <unordered_map>
32template <
typename MeshType_>
35 using MeshType = MeshType_;
36 using Index =
typename MeshType::Index;
37 using IndexList =
typename MeshType::IndexList;
38 using Scalar =
typename MeshType::Scalar;
39 using VertexArray =
typename MeshType::VertexArray;
40 using EdgeArray = Eigen::Matrix<Index, Eigen::Dynamic, 2, Eigen::RowMajor>;
47 IndexList vertices_parent_edge;
51 std::vector<Scalar> vertices_parent_param;
68template <
typename MeshType,
typename ValueFn>
71 ScalarOf<MeshType> isovalue,
72 const ValueFn& get_value)
75 using Index =
typename MeshType::Index;
76 using Scalar =
typename MeshType::Scalar;
77 using VertexType =
typename MeshType::VertexType;
81 la_runtime_assert(mesh_ref.get_vertex_per_facet() == 3,
"only works for triangle meshes");
84 const auto& facets = mesh_ref.get_facets();
85 const auto& vertices = mesh_ref.get_vertices();
87 std::vector<Edge> extracted_edges;
88 std::vector<VertexType> extracted_vertices;
89 std::vector<Index> extracted_vertices_parent_edge;
90 std::vector<Scalar> extracted_vertices_parent_param;
91 std::vector<Index> parent_edge_to_extracted_vertex(mesh_ref.
get_num_edges(), invalid<Index>());
98 auto find_zero = [&](Index parent_edge_id, Index v0, Index v1, Scalar p0, Scalar p1) -> Index {
99 if (parent_edge_to_extracted_vertex[parent_edge_id] != invalid<Index>()) {
100 return parent_edge_to_extracted_vertex[parent_edge_id];
104 if ((v0 == parent_edge[1]) && (v1 == parent_edge[0])) {
108 assert((v1 == parent_edge[1]) && (v0 == parent_edge[0]));
110 const Scalar a = p1 / (p1 - p0);
111 const Scalar b = 1 - a;
118 const Index vertex_index = safe_cast<Index>(extracted_vertices.size());
119 const VertexType pos0 = vertices.row(v0);
120 const VertexType pos1 = vertices.row(v1);
122 extracted_vertices.emplace_back(a * pos0 + b * pos1);
123 extracted_vertices_parent_edge.emplace_back(parent_edge_id);
124 extracted_vertices_parent_param.emplace_back(b);
125 parent_edge_to_extracted_vertex[parent_edge_id] = vertex_index;
133 auto contour_triangle = [&](
const Index tri_id) {
134 const Index v0 = facets(tri_id, 0);
135 const Index v1 = facets(tri_id, 1);
136 const Index v2 = facets(tri_id, 2);
137 Scalar p0 = get_value(tri_id, 0) - isovalue;
138 Scalar p1 = get_value(tri_id, 1) - isovalue;
139 Scalar p2 = get_value(tri_id, 2) - isovalue;
141 const Index e01 = mesh_ref.
get_edge(tri_id, 0);
142 const Index e12 = mesh_ref.
get_edge(tri_id, 1);
143 const Index e20 = mesh_ref.
get_edge(tri_id, 2);
146 if (p0 == 0) p0 = Scalar(1e-30);
147 if (p1 == 0) p1 = Scalar(1e-30);
148 if (p2 == 0) p2 = Scalar(1e-30);
155 extracted_edges.push_back(
156 Edge(find_zero(e12, v1, v2, p1, p2), find_zero(e20, v0, v2, p0, p2)));
160 extracted_edges.push_back(
161 Edge(find_zero(e01, v0, v1, p0, p1), find_zero(e12, v1, v2, p1, p2)));
163 extracted_edges.push_back(
164 Edge(find_zero(e01, v0, v1, p0, p1), find_zero(e20, v0, v2, p0, p2)));
170 extracted_edges.push_back(
171 Edge(find_zero(e20, v0, v2, p0, p2), find_zero(e01, v0, v1, p0, p1)));
173 extracted_edges.push_back(
174 Edge(find_zero(e12, v1, v2, p1, p2), find_zero(e01, v0, v1, p0, p1)));
178 extracted_edges.push_back(
179 Edge(find_zero(e20, v0, v2, p0, p2), find_zero(e12, v1, v2, p1, p2)));
191 for (
auto tri :
range(mesh_ref.get_num_facets())) {
192 contour_triangle(tri);
198 MarchingTrianglesOutput output;
200 output.edges.resize(extracted_edges.size(), 2);
201 for (
auto i :
range(extracted_edges.size())) {
202 output.edges.row(i) << extracted_edges[i][0], extracted_edges[i][1];
206 output.vertices_parent_edge.swap(extracted_vertices_parent_edge);
207 output.vertices_parent_param.swap(extracted_vertices_parent_param);
209 output.vertices.resize(extracted_vertices.size(), mesh_ref.get_dim());
210 for (
auto i :
range(extracted_vertices.size())) {
211 output.vertices.row(i) = extracted_vertices[i];
230template <
typename MeshType>
231MarchingTrianglesOutput<MeshType> marching_triangles(
233 const typename MeshType::Scalar isovalue,
234 const std::string vertex_attribute_name,
235 const typename MeshType::Index attribute_col_index = 0)
237 using Index = IndexOf<MeshType>;
239 mesh_ref.has_vertex_attribute(vertex_attribute_name),
240 "attribute does not exist in the mesh");
241 const auto& attribute = mesh_ref.get_vertex_attribute(vertex_attribute_name);
243 attribute_col_index < safe_cast<Index>(attribute.cols()),
244 "col_index is invalid");
246 const auto& facets = mesh_ref.get_facets();
247 return marching_triangles_general(mesh_ref, isovalue, [&](Index fi, Index ci) {
248 return attribute(facets(fi, ci), attribute_col_index);
268template <
typename MeshType>
269MarchingTrianglesOutput<MeshType> marching_triangles_indexed(
271 const typename MeshType::Scalar isovalue,
272 const std::string indexed_attribute_name,
273 const typename MeshType::Index attribute_col_index = 0)
275 using Index = IndexOf<MeshType>;
277 mesh_ref.has_indexed_attribute(indexed_attribute_name),
278 "attribute does not exist in the mesh");
279 const auto& attribute = mesh_ref.get_indexed_attribute(indexed_attribute_name);
281 attribute_col_index < safe_cast<Index>(std::get<0>(attribute).cols()),
282 "col_index is invalid");
284 return marching_triangles_general(mesh_ref, isovalue, [&](Index fi, Index ci) {
285 return std::get<0>(attribute)(std::get<1>(attribute)(fi, ci), attribute_col_index);
Index get_edge(Index f, Index lv) const
Gets the edge index corresponding to (f, lv) – (f, lv+1).
Definition: Mesh.h:664
std::array< Index, 2 > get_edge_vertices(Index e) const
Retrieve edge endpoints.
Definition: Mesh.h:730
void initialize_edge_data()
Edge data initialization.
Definition: Mesh.h:633
Index get_num_edges() const
Gets the number of edges.
Definition: Mesh.h:650
@ Edge
Per-edge mesh attributes.
Definition: AttributeFwd.h:34
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
constexpr void swap(function_ref< R(Args...)> &lhs, function_ref< R(Args...)> &rhs) noexcept
Swaps the referred callables of lhs and rhs.
Definition: function_ref.h:114
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition: range.h:176
Main namespace for Lagrange.
Definition: AABBIGL.h:30
MeshTrait class provide compiler check for different mesh types.
Definition: MeshTrait.h:108
Definition: marching_triangles.h:34