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 Vector2r to_rational(const Vector2d& p0)
52{
53 Vector2r p(p0[0], p0[1]);
54 return p;
55}
56
57inline Vector3r to_rational(const Vector3d& p0)
58{
59 Vector3r p(p0[0], p0[1], p0[2]);
60 return p;
61}
62
63inline Vector2d to_double(const Vector2r& p0)
64{
65 Vector2d p(p0[0].to_double(), p0[1].to_double());
66 return p;
67}
68
69inline Vector3d to_double(const Vector3r& p0)
70{
71 Vector3d p(p0[0].to_double(), p0[1].to_double(), p0[2].to_double());
72 return p;
73}
74
75inline Vector4d to_homogenuous(const Vector3d& x)
76{
77 return Vector4d(x[0], x[1], x[2], 1);
78}
79
80inline Vector3d from_homogenuous(const Vector4d& x)
81{
82 return Vector3d(x[0] / x[3], x[1] / x[3], x[2] / x[3]);
83}
84
85using V_MAP = Eigen::Map<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>>;
86using F_MAP = Eigen::Map<const Eigen::Matrix<int, -1, -1, Eigen::RowMajor>>;
87
88inline void vectors_to_VF(
89 const std::vector<Vector3d>& vertices,
90 const std::vector<std::array<size_t, 3>>& faces,
91 MatrixXd& V,
92 MatrixXi& F)
93{
94 V.resize(vertices.size(), 3);
95 F.resize(faces.size(), 3);
96
97 for (int i = 0; i < V.rows(); i++) {
98 V.row(i) = vertices[i];
99 }
100 for (int i = 0; i < F.rows(); i++) {
101 F.row(i) = Vector3i((int)faces[i][0], (int)faces[i][1], (int)faces[i][2]);
102 }
103}
104
105inline void VF_to_vectors(
106 const MatrixXd& V,
107 const MatrixXi& F,
108 std::vector<Vector3d>& vertices,
109 std::vector<std::array<size_t, 3>>& faces)
110{
111 vertices.resize(V.rows());
112 faces.resize(F.rows());
113
114 for (int i = 0; i < V.rows(); i++) {
115 vertices[i] = V.row(i);
116 }
117 for (int i = 0; i < F.rows(); i++) {
118 faces[i][0] = F(i, 0);
119 faces[i][1] = F(i, 1);
120 faces[i][2] = F(i, 2);
121 }
122}
123
124inline bool
125tet_is_inverted(const Vector3d& v0, const Vector3d& v1, const Vector3d& v2, const Vector3d& v3)
126{
127 igl::predicates::exactinit();
128 auto res = igl::predicates::orient3d(v0, v1, v2, v3);
129 int result;
130 if (res == igl::predicates::Orientation::POSITIVE)
131 result = 1;
132 else if (res == igl::predicates::Orientation::NEGATIVE)
133 result = -1;
134 else
135 result = 0;
136
137 if (result < 0) // neg result == pos tet (tet origin from geogram delaunay)
138 return false;
139 return true;
140}
141
142inline bool tri_is_inverted(const Vector2d& v0, const Vector2d& v1, const Vector2d& v2)
143{
144 igl::predicates::exactinit();
145 auto res = igl::predicates::orient2d(v0, v1, v2);
146 int result;
147 if (res == igl::predicates::Orientation::POSITIVE)
148 result = 1;
149 else if (res == igl::predicates::Orientation::NEGATIVE)
150 result = -1;
151 else
152 result = 0;
153
154 if (result < 0) // neg result == pos tet (tet origin from geogram delaunay)
155 return false;
156 return true;
157}
158
164inline bool VF_rational_to_double(const MatrixXr& V_in, const MatrixXi& F, MatrixXd& V_out)
165{
166 V_out.resizeLike(V_in);
167 for (int i = 0; i < V_in.size(); ++i) {
168 V_out(i) = V_in(i).to_double();
169 }
170
171 // check for inversion
172 if (F.cols() == 3) {
173 // 2D
174 for (int i = 0; i < F.rows(); ++i) {
175 const auto& s = F.row(i);
176 if (tri_is_inverted(V_out.row(s[0]), V_out.row(s[1]), V_out.row(s[2]))) {
177 return false;
178 }
179 }
180 } else if (F.cols() == 4) {
181 // 3D
182 for (int i = 0; i < F.rows(); ++i) {
183 const auto& s = F.row(i);
184 if (tet_is_inverted(
185 V_out.row(s[0]),
186 V_out.row(s[1]),
187 V_out.row(s[2]),
188 V_out.row(s[3]))) {
189 return false;
190 }
191 }
192 } else {
193 log_and_throw_error("Unknown dimension in VF_rational_to_double");
194 }
195
196 return true;
197}
198
199} // namespace wmtk
200
201// Enables passing Eigen matrices to fmt/spdlog.
202template <typename T>
203struct fmt::formatter<
204 T,
205 std::enable_if_t<
206 std::is_base_of_v<Eigen::DenseBase<T>, T> && !fmt::is_range<T, char>::value,
207 char>> : ostream_formatter
208{
209};