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