Wildmeshing Toolkit
Loading...
Searching...
No Matches
TetWildTangentialLaplacianSmoothing.cpp
Go to the documentation of this file.
2
3#include <wmtk/Mesh.hpp>
4#include <wmtk/TriMesh.hpp>
9
10#include <wmtk/simplex/link.hpp>
11
12namespace wmtk::operations {
13
15 Mesh& m,
16 const TypedAttributeHandle<Rational>& coordinate,
17 double damping_factor)
19 , m_coordinate_handle(coordinate)
20 , m_damping_factor(damping_factor)
21{
22 assert(mesh().top_simplex_type() == PrimitiveType::Triangle);
23}
24
26 const simplex::Simplex& simplex)
27{
28 // normal laplacian smoothing
29 auto accessor = mesh().create_accessor(m_coordinate_handle);
30 const auto old_pos = accessor.const_vector_attribute(simplex.tuple()).cast<double>();
31
32 const auto one_ring = simplex::link(mesh(), simplex).simplex_vector(PrimitiveType::Vertex);
33
34 Vector3d new_pos(0, 0, 0);
35 for (const auto& v : one_ring) {
36 new_pos = new_pos + accessor.const_vector_attribute(v).cast<double>();
37 }
38
39 new_pos = new_pos / one_ring.size();
40
41 // tangential
42 if (mesh().is_boundary(PrimitiveType::Vertex, simplex.tuple())) {
43 Tuple t0 = simplex.tuple();
44 while (!mesh().is_boundary(PrimitiveType::Edge, t0)) {
46 }
47
49
51 while (!mesh().is_boundary(PrimitiveType::Edge, t1)) {
53 }
55
56 const Vector3d p0 = accessor.const_vector_attribute(v0).cast<double>();
57 const Vector3d p1 = accessor.const_vector_attribute(v1).cast<double>();
58
59 const Vector3d tang = (p1 - p0).normalized();
60
61 new_pos = old_pos + m_damping_factor * tang * tang.transpose() * (new_pos - old_pos);
62 } else {
63 Tuple t = simplex.tuple();
64
65 Vector3d n(0, 0, 0);
66
67 for (int64_t i = 0; i < one_ring.size(); ++i) {
68 const Vector3d p0 = accessor.const_vector_attribute(t).cast<double>();
69 const Vector3d p1 =
70 accessor.const_vector_attribute(mesh().switch_tuple(t, PrimitiveType::Vertex))
71 .cast<double>();
72 const Vector3d p2 =
73 accessor
74 .const_vector_attribute(
76 .cast<double>();
77
78 Vector3d weighted_ni = (p0 - p2).cross(p1 - p2);
79
80 n = n + weighted_ni;
81
83 }
84
85 n.normalized();
86 new_pos = old_pos + m_damping_factor * (Eigen::Matrix3d::Identity() - n * n.transpose()) *
87 (new_pos - old_pos);
88 }
89
90 accessor.vector_attribute(simplex) = Vector3r(
91 Rational(new_pos[0], true),
92 Rational(new_pos[1], true),
93 Rational(new_pos[2], true));
94
95 return AttributesUpdate::execute(simplex);
96}
97
98} // namespace wmtk::operations
bool is_boundary(const simplex::Simplex &tuple) const
check if a simplex lies on a boundary or not
Definition Mesh.cpp:107
attribute::Accessor< T, Mesh, D > create_accessor(const attribute::MeshAttributeHandle &handle)
Tuple switch_tuples(const Tuple &tuple, const ContainerType &op_sequence) const
Definition Mesh.hpp:953
virtual Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const =0
switch the orientation of the Tuple of the given dimension
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
Handle that represents attributes for some mesh.
virtual std::vector< simplex::Simplex > execute(const simplex::Simplex &simplex) override
returns an empty vector in case of failure
const Mesh & mesh() const
Definition Operation.hpp:45
std::vector< simplex::Simplex > execute(const simplex::Simplex &simplex) override
returns an empty vector in case of failure
TetWildTangentialLaplacianSmoothing(Mesh &m, const TypedAttributeHandle< Rational > &coordinate, double damping_factor=1.0)
const std::vector< Simplex > & simplex_vector() const
Return const reference to the simplex vector.
const Tuple & tuple() const
Definition Simplex.hpp:53
SimplexCollection link(const Mesh &mesh, const simplex::Simplex &simplex, const bool sort_and_clean)
Definition link.cpp:84
Vector< Rational, 3 > Vector3r
Definition Types.hpp:41
Vector< double, 3 > Vector3d
Definition Types.hpp:39