MeshLib C++ Docs
Loading...
Searching...
No Matches
MRPrecisePredicates3Poly.h
Go to the documentation of this file.
1#pragma once
2
4#include "MRInt64Mul128.h"
5#include "MRMacros.h"
7#include <algorithm>
8#include <array>
9#include <cassert>
10#include <limits>
11#include <type_traits>
12#include <vector>
13
14namespace MR
15{
16
19
21namespace detail
22{
23
26
29[[nodiscard]] MR_FORCE_INLINE FastInt128 orient3dVolume( const Vector3i & a, const Vector3i & b, const Vector3i & c, const Vector3i & d )
30{
31 const Vector3i64 x( a - d );
32 const Vector3i64 y( b - d );
33 const Vector3i64 z( c - d );
34
35 return
36 Int64Mul128( x.x ) * Int64Mul128( y.y * z.z - y.z * z.y )
37 - Int64Mul128( x.y ) * Int64Mul128( y.x * z.z - y.z * z.x )
38 + Int64Mul128( x.z ) * Int64Mul128( y.x * z.y - y.y * z.x );
39}
40
43{
44 Vector3i pt;
45 std::int64_t d = 0;
46
48 [[nodiscard]] std::int64_t degree( int i ) const
49 {
50 constexpr std::int64_t w[3] = { 9, 3, 1 };
51 return w[i] * d;
52 }
53};
54
56constexpr int cMaxPerturbedPoints = 16;
57
67template <int N = cMaxPerturbedPoints, bool Bounded = false>
68MR_FORCE_INLINE int getPointDegrees( const PreciseVertCoords * vs, const std::int64_t * radices, int n, PointDegree * res,
69 std::int64_t * places = nullptr )
70{
71 struct VertN
72 {
73 VertId v;
74 int n = 0;
75 };
76 assert( n > 0 && n <= N );
77 std::array<VertN, N> as;
78 for ( int i = 0; i < n; ++i )
79 as[i] = { vs[i].id, i };
80 std::sort( as.begin(), as.begin() + n, []( const auto & a, const auto & b ) { return a.v < b.v; } );
81
82 std::int64_t d = 1;
83 int numIds = 1;
84 if ( places )
85 places[0] = d;
86 for ( int i = 0; i < n; ++i )
87 {
88 const auto k = as[i].n;
89 if constexpr ( Bounded )
90 {
91 if ( d > std::numeric_limits<std::int64_t>::max() / radices[k] )
92 {
94 for ( int j = i; j < n; ++j )
95 res[as[j].n] = { vs[as[j].n].pt, 0 };
96 return numIds - 1;
97 }
98 }
99 res[k] = { vs[k].pt, d };
100 if ( i + 1 == n )
101 break;
102 const auto r = radices[k];
103 if ( as[i].v < as[i+1].v )
104 {
105 assert( d <= std::numeric_limits<std::int64_t>::max() / r );
106 d *= r;
107 if ( places )
108 places[numIds] = d;
109 ++numIds;
110 }
111 else
112 assert( r == radices[as[i+1].n] );
113 }
114 return numIds;
115}
116
118constexpr std::int64_t cMaxPolyDAll = std::numeric_limits<std::int64_t>::max();
119
125constexpr std::int64_t cMaxPolyDTriTri = 15'943'959;
126constexpr std::int64_t cMaxPolyDTriPlane = 430'486'893;
127
135template <int N, bool Bounded>
137{
138public:
140 MR_FORCE_INLINE PerturbationStagesOf( const PreciseVertCoords * vs, const std::int64_t * radices, int n )
141 {
142 assert( n <= N );
143 numStages_ = getPointDegrees<N, Bounded>( vs, radices, n, points_.data(), places_.data() );
144 }
145
147 [[nodiscard]] int numStages() const { return numStages_; }
148
150 [[nodiscard]] std::int64_t place( int s ) const { return places_[s - 1]; }
151
153 [[nodiscard]] const PointDegree & operator[]( int i ) const { return points_[i]; }
154
156 [[nodiscard]] PointDegree at( int i, int s ) const { return points_[i].d <= place( s ) ? points_[i] : PointDegree{ points_[i].pt, 0 }; }
157
159 [[nodiscard]] bool startsAt( int i, int s ) const { return points_[i].d == place( s ); }
160
163 template <typename F>
164 [[nodiscard]] auto firstStage( F && f, std::int64_t maxDeg = cMaxPolyDAll ) const -> std::invoke_result_t<F &, int>
165 {
166 for ( int s = 1; s <= numStages_ && place( s ) <= maxDeg; ++s )
167 if ( auto res = f( s ) )
168 return res;
169 return {};
170 }
171
172private:
173 std::array<PointDegree, N> points_;
174 std::array<std::int64_t, N> places_;
175 int numStages_ = 0;
176};
177
180
183template <std::int64_t M>
185
187template <std::int64_t M>
188[[nodiscard]] VolumePoly<M> orient3dPoly( const PointDegree & a, const PointDegree & b, const PointDegree & c, const PointDegree & d )
189{
192 struct Element
193 {
194 typename VolumePoly<M>::Term terms[3];
195 int numTerms = 0;
196 };
197 Element m[3][3];
198 const PointDegree * rows[3] = { &a, &b, &c };
199 for ( int r = 0; r < 3; ++r )
200 for ( int col = 0; col < 3; ++col )
201 {
202 auto & e = m[r][col];
203 if ( const std::int64_t delta = std::int64_t( rows[r]->pt[col] ) - d.pt[col] )
204 e.terms[e.numTerms++] = { 0, delta };
205 if ( rows[r]->d )
206 e.terms[e.numTerms++] = { rows[r]->degree( col ), 1 };
207 if ( d.d )
208 e.terms[e.numTerms++] = { d.degree( col ), -1 };
209 }
210
213 constexpr int perms[6][4] = { { 0, 1, 2, 1 }, { 1, 2, 0, 1 }, { 2, 0, 1, 1 }, { 0, 2, 1, -1 }, { 2, 1, 0, -1 }, { 1, 0, 2, -1 } };
214 std::vector<typename VolumePoly<M>::Term> terms;
215 terms.reserve( 6 * 26 );
216 for ( const auto & p : perms )
217 {
218 const Element & e0 = m[0][p[0]];
219 const Element & e1 = m[1][p[1]];
220 const Element & e2 = m[2][p[2]];
221 for ( int k0 = 0; k0 < e0.numTerms; ++k0 )
222 for ( int k1 = 0; k1 < e1.numTerms; ++k1 )
223 {
225 const std::int64_t c01 = p[3] * std::int64_t( e0.terms[k0].second ) * std::int64_t( e1.terms[k1].second );
226 const std::int64_t d01 = e0.terms[k0].first + e1.terms[k1].first;
227 const int last2 = d.d && k0 + 1 == e0.numTerms && k1 + 1 == e1.numTerms ? e2.numTerms - 1 : e2.numTerms;
228 for ( int k2 = 0; k2 < last2; ++k2 )
229 if ( const auto deg = d01 + e2.terms[k2].first; deg <= M )
230 terms.emplace_back( deg, Int64Mul128( c01 ) * Int64Mul128( std::int64_t( e2.terms[k2].second ) ) );
231 }
232 }
233 return VolumePoly<M>::fromUnsortedTerms( std::move( terms ) );
234}
235
236}
237
239
240}
#define MR_FORCE_INLINE
Definition MRMacros.h:47
#define M(T)
Definition MRInt64Mul128.h:22
Definition MRSparsePolynomial.h:75
segmentIntersectionTriPlaneOrder: it reaches the polynomial path with all three largest ids in the pl...
Definition MRPrecisePredicates3Poly.h:137
const PointDegree & operator[](int i) const
point i with its degree, as perturbed at the last stage (if Bounded, with the degree 0 if no stage pe...
Definition MRPrecisePredicates3Poly.h:153
PointDegree at(int i, int s) const
point i as perturbed at stage s
Definition MRPrecisePredicates3Poly.h:156
bool startsAt(int i, int s) const
whether point i is perturbed first at stage s
Definition MRPrecisePredicates3Poly.h:159
MR_FORCE_INLINE PerturbationStagesOf(const PreciseVertCoords *vs, const std::int64_t *radices, int n)
the stages of points vs[0..n-1] with the degrees from getPointDegrees
Definition MRPrecisePredicates3Poly.h:140
auto firstStage(F &&f, std::int64_t maxDeg=cMaxPolyDAll) const -> std::invoke_result_t< F &, int >
Definition MRPrecisePredicates3Poly.h:164
std::int64_t place(int s) const
the degree of the points perturbed first at stage s: every term with them has at least this degree,...
Definition MRPrecisePredicates3Poly.h:150
int numStages() const
the number of stages, which is the number of different ids (if Bounded, of those before the first one...
Definition MRPrecisePredicates3Poly.h:147
Vector3i pt
integer coordinates of the vertex
Definition MRPrecisePredicates3.h:40
std::pair< std::int64_t, FastInt128 > Term
Definition MRSparsePolynomial.h:79
static SparsePolynomial fromUnsortedTerms(std::vector< Term > &&terms)
VertId id
unique id of the vertex (in both meshes)
Definition MRPrecisePredicates3.h:39
for internal use: namespace detail is not bound to other languages
Definition MRFastInt.h:19
VolumePoly< M > orient3dPoly(const PointDegree &a, const PointDegree &b, const PointDegree &c, const PointDegree &d)
the volume of tetrahedron abcd (see orient3dVolume) of the perturbed points as a polynomial of eps,...
Definition MRPrecisePredicates3Poly.h:188
SparsePolynomial< FastInt128, std::int64_t, M > VolumePoly
Definition MRPrecisePredicates3Poly.h:184
constexpr int cMaxPerturbedPoints
the largest number of points of one predicate that getPointDegrees and PerturbationStages take by def...
Definition MRPrecisePredicates3Poly.h:56
PerturbationStagesOf< cMaxPerturbedPoints, false > PerturbationStages
the stages of at most cMaxPerturbedPoints points, whose degrees the caller makes fit in int64
Definition MRPrecisePredicates3Poly.h:179
MR_FORCE_INLINE int getPointDegrees(const PreciseVertCoords *vs, const std::int64_t *radices, int n, PointDegree *res, std::int64_t *places=nullptr)
Definition MRPrecisePredicates3Poly.h:68
MR_FORCE_INLINE FastInt128 orient3dVolume(const Vector3i &a, const Vector3i &b, const Vector3i &c, const Vector3i &d)
Definition MRPrecisePredicates3Poly.h:29
constexpr std::int64_t cMaxPolyDAll
the largest degree that no term exceeds: a polynomial with it keeps all its terms
Definition MRPrecisePredicates3Poly.h:118
constexpr std::int64_t cMaxPolyDTriTri
Definition MRPrecisePredicates3Poly.h:125
constexpr std::int64_t cMaxPolyDTriPlane
segmentIntersectionOrder
Definition MRPrecisePredicates3Poly.h:126
Only strictly necessary for the bindings (to make MR::MeshIntersectionResult a complete type).
Definition MRCameraOrientationPlugin.h:8
__int128_t FastInt128
Definition MRFastInt128.h:22
Definition MRPrecisePredicates3.h:38
a point with the degree of its perturbation: its coordinates z, y, x get eps^d, eps^(3*d),...
Definition MRPrecisePredicates3Poly.h:43
Vector3i pt
Definition MRPrecisePredicates3Poly.h:44
std::int64_t degree(int i) const
the degree of epsilon for coordinate i
Definition MRPrecisePredicates3Poly.h:48
std::int64_t d
degree of epsilon for pt.z; 0 leaves the point unperturbed
Definition MRPrecisePredicates3Poly.h:45