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