Wildmeshing Toolkit
Loading...
Searching...
No Matches
predicates.hpp
1#pragma once
2
3#include <Eigen/Core>
4
5namespace wmtk::utils::predicates {
6
14enum class Orientation {
15 POSITIVE = 1,
16 INSIDE = 1,
17 NEGATIVE = -1,
18 OUTSIDE = -1,
19 COLLINEAR = 0,
20 COPLANAR = 0,
21 COCIRCULAR = 0,
22 COSPHERICAL = 0,
23 DEGENERATE = 0
24};
25
26namespace detail {
27
44int orient2d_sign(double ax, double ay, double bx, double by, double cx, double cy);
45int orient3d_sign(
46 double ax,
47 double ay,
48 double az,
49 double bx,
50 double by,
51 double bz,
52 double cx,
53 double cy,
54 double cz,
55 double dx,
56 double dy,
57 double dz);
58
59inline Orientation from_sign(const int s)
60{
61 return s > 0 ? Orientation::POSITIVE : (s < 0 ? Orientation::NEGATIVE : Orientation::COLLINEAR);
62}
63
64} // namespace detail
65
74inline void exactinit() {}
75
82template <typename D0, typename D1, typename D2>
83inline Orientation orient2d(
84 const Eigen::MatrixBase<D0>& a,
85 const Eigen::MatrixBase<D1>& b,
86 const Eigen::MatrixBase<D2>& c)
87{
88 return detail::from_sign(detail::orient2d_sign(a[0], a[1], b[0], b[1], c[0], c[1]));
89}
90
103template <typename D0, typename D1, typename D2, typename D3>
104inline Orientation orient3d(
105 const Eigen::MatrixBase<D0>& a,
106 const Eigen::MatrixBase<D1>& b,
107 const Eigen::MatrixBase<D2>& c,
108 const Eigen::MatrixBase<D3>& d)
109{
110 return detail::from_sign(
111 detail::
112 orient3d_sign(a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2], d[0], d[1], d[2]));
113}
114
118template <typename D0, typename D1, typename D2>
119inline bool is_degenerate(
120 const Eigen::MatrixBase<D0>& v0,
121 const Eigen::MatrixBase<D1>& v1,
122 const Eigen::MatrixBase<D2>& v2)
123{
124 if constexpr (Eigen::MatrixBase<D0>::RowsAtCompileTime == 3) {
125 // Three points in 3D are collinear only if they are collinear in all three
126 // coordinate-plane projections; any one projection can flatten a real triangle.
127 for (int dim = 0; dim < 3; ++dim) {
128 const Eigen::Vector2d p0(v0[dim], v0[(dim + 1) % 3]);
129 const Eigen::Vector2d p1(v1[dim], v1[(dim + 1) % 3]);
130 const Eigen::Vector2d p2(v2[dim], v2[(dim + 1) % 3]);
131 if (orient2d(p0, p1, p2) != Orientation::COLLINEAR) {
132 return false;
133 }
134 }
135 return true;
136 } else {
137 return orient2d(v0, v1, v2) == Orientation::COLLINEAR;
138 }
139}
140
144template <typename D0, typename D1, typename D2, typename D3>
145inline bool is_degenerate(
146 const Eigen::MatrixBase<D0>& v0,
147 const Eigen::MatrixBase<D1>& v1,
148 const Eigen::MatrixBase<D2>& v2,
149 const Eigen::MatrixBase<D3>& v3)
150{
151 return orient3d(v0, v1, v2, v3) == Orientation::COPLANAR;
152}
153
161inline bool faces_along(
162 const Eigen::Vector3d& a,
163 const Eigen::Vector3d& b,
164 const Eigen::Vector3d& c,
165 const Eigen::Vector3d& n)
166{
167 const Eigen::Vector3d below = a - (1 + a.lpNorm<Eigen::Infinity>()) * n.normalized();
168 return orient3d(a, b, c, below) == Orientation::POSITIVE;
169}
170
171} // namespace wmtk::utils::predicates