Wildmeshing Toolkit
Loading...
Searching...
No Matches
Types.hpp
1#pragma once
2
3#include <igl/predicates/predicates.h>
4#include <Eigen/Core>
5#include <Eigen/Sparse>
6#include <wmtk/utils/Logger.hpp>
7#include <wmtk/utils/Rational.hpp>
8
9namespace wmtk {
10
11template <typename T>
12using MatrixX = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
13
14using MatrixXd = MatrixX<double>;
15using MatrixXi = MatrixX<int>;
16using MatrixXr = MatrixX<Rational>;
17using Matrix2d = Eigen::Matrix2d;
18using Matrix3d = Eigen::Matrix3d;
19using Matrix4d = Eigen::Matrix4d;
20
21template <typename T>
22using MatrixS = Eigen::SparseMatrix<T>;
23
24using MatrixSi = MatrixS<int>;
25using MatrixSd = MatrixS<double>;
26
27template <typename T, int R>
28using Vector = Eigen::Matrix<T, R, 1>;
29template <typename T>
30using VectorX = Vector<T, Eigen::Dynamic>;
31
32using Vector2d = Vector<double, 2>;
33using Vector3d = Vector<double, 3>;
34using Vector4d = Vector<double, 4>;
35using VectorXd = Vector<double, Eigen::Dynamic>;
36
37using Vector2r = Vector<Rational, 2>;
38using Vector3r = Vector<Rational, 3>;
39
40using Vector2i = Vector<int, 2>;
41using Vector3i = Vector<int, 3>;
42using Vector4i = Vector<int, 4>;
43using VectorXi = Vector<int, Eigen::Dynamic>;
44
45template <typename T>
46using VectorS = Eigen::SparseVector<T>;
47
48using VectorSi = VectorS<int>;
49using VectorSd = VectorS<double>;
50
51inline Vector3r to_rational(const Vector3d& p0)
52{
53 Vector3r p(p0[0], p0[1], p0[2]);
54 return p;
55}
56
57inline Vector3d to_double(const Vector3r& p0)
58{
59 Vector3d p(p0[0].to_double(), p0[1].to_double(), p0[2].to_double());
60 return p;
61}
62
63inline Vector4d to_homogenuous(const Vector3d& x)
64{
65 return Vector4d(x[0], x[1], x[2], 1);
66}
67
68inline Vector3d from_homogenuous(const Vector4d& x)
69{
70 return Vector3d(x[0] / x[3], x[1] / x[3], x[2] / x[3]);
71}
72
73using V_MAP = Eigen::Map<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>>;
74using F_MAP = Eigen::Map<const Eigen::Matrix<int, -1, -1, Eigen::RowMajor>>;
75
76inline void vectors_to_VF(
77 const std::vector<Vector3d>& vertices,
78 const std::vector<std::array<size_t, 3>>& faces,
79 MatrixXd& V,
80 MatrixXi& F)
81{
82 V.resize(vertices.size(), 3);
83 F.resize(faces.size(), 3);
84
85 for (int i = 0; i < V.rows(); i++) {
86 V.row(i) = vertices[i];
87 }
88 for (int i = 0; i < F.rows(); i++) {
89 F.row(i) = Vector3i((int)faces[i][0], (int)faces[i][1], (int)faces[i][2]);
90 }
91}
92
93inline void VF_to_vectors(
94 const MatrixXd& V,
95 const MatrixXi& F,
96 std::vector<Vector3d>& vertices,
97 std::vector<std::array<size_t, 3>>& faces)
98{
99 vertices.resize(V.rows());
100 faces.resize(F.rows());
101
102 for (int i = 0; i < V.rows(); i++) {
103 vertices[i] = V.row(i);
104 }
105 for (int i = 0; i < F.rows(); i++) {
106 faces[i][0] = F(i, 0);
107 faces[i][1] = F(i, 1);
108 faces[i][2] = F(i, 2);
109 }
110}
111
112inline bool
113tet_is_inverted(const Vector3d& v0, const Vector3d& v1, const Vector3d& v2, const Vector3d& v3)
114{
115 igl::predicates::exactinit();
116 auto res = igl::predicates::orient3d(v0, v1, v2, v3);
117 int result;
118 if (res == igl::predicates::Orientation::POSITIVE)
119 result = 1;
120 else if (res == igl::predicates::Orientation::NEGATIVE)
121 result = -1;
122 else
123 result = 0;
124
125 if (result < 0) // neg result == pos tet (tet origin from geogram delaunay)
126 return false;
127 return true;
128}
129
130inline bool tri_is_inverted(const Vector2d& v0, const Vector2d& v1, const Vector2d& v2)
131{
132 igl::predicates::exactinit();
133 auto res = igl::predicates::orient2d(v0, v1, v2);
134 int result;
135 if (res == igl::predicates::Orientation::POSITIVE)
136 result = 1;
137 else if (res == igl::predicates::Orientation::NEGATIVE)
138 result = -1;
139 else
140 result = 0;
141
142 if (result < 0) // neg result == pos tet (tet origin from geogram delaunay)
143 return false;
144 return true;
145}
146
152inline bool VF_rational_to_double(const MatrixXr& V_in, const MatrixXi& F, MatrixXd& V_out)
153{
154 V_out.resizeLike(V_in);
155 for (int i = 0; i < V_in.size(); ++i) {
156 V_out(i) = V_in(i).to_double();
157 }
158
159 // check for inversion
160 if (F.cols() == 3) {
161 // 2D
162 for (int i = 0; i < F.rows(); ++i) {
163 const auto& s = F.row(i);
164 if (tri_is_inverted(V_out.row(s[0]), V_out.row(s[1]), V_out.row(s[2]))) {
165 return false;
166 }
167 }
168 } else if (F.cols() == 4) {
169 // 3D
170 for (int i = 0; i < F.rows(); ++i) {
171 const auto& s = F.row(i);
172 if (tet_is_inverted(
173 V_out.row(s[0]),
174 V_out.row(s[1]),
175 V_out.row(s[2]),
176 V_out.row(s[3]))) {
177 return false;
178 }
179 }
180 } else {
181 log_and_throw_error("Unknown dimension in VF_rational_to_double");
182 }
183
184 return true;
185}
186
187} // namespace wmtk
188
189// Enables passing Eigen matrices to fmt/spdlog.
190template <typename T>
191struct fmt::formatter<
192 T,
193 std::enable_if_t<
194 std::is_base_of_v<Eigen::DenseBase<T>, T> && !fmt::is_range<T, char>::value,
195 char>> : ostream_formatter
196{
197};