Skip to content

Commit c849eb5

Browse files
GrantimFedr
andauthored
Planar triangulations use SoS (#4435)
* planar_triangulations_use_SoS * add test * Update * add comment * simplify test * fix build * update comment --------- Co-authored-by: Fedor Chelnokov <fedor.chelnokov@meshinspector.com>
1 parent 8e1d45d commit c849eb5

7 files changed

+279
-115
lines changed

source/MRMesh/MR2DContoursTriangulation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class SweepLineQueue
139139

140140
bool less_( VertId l, VertId r ) const
141141
{
142-
return std::tuple( pts_[l].x, pts_[l].y, l ) < std::tuple( pts_[r].x, pts_[r].y, r );
142+
return smaller( { .id = l,.pt = pts_[l].x }, { .id = r,.pt = pts_[r].x } );
143143
}
144144

145145
// INITIALIZATION CLASS BLOCK

source/MRMesh/MRHighPrecision.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ namespace MR
1111
/// \{
1212

1313
using HighPrecisionInt = boost::multiprecision::checked_int128_t;
14+
using HighHighPrecisionInt = boost::multiprecision::checked_int256_t;
1415

1516
using Vector2hp = Vector2<HighPrecisionInt>;
1617
using Vector3hp = Vector3<HighPrecisionInt>;
18+
using Vector3hhp = Vector3<HighHighPrecisionInt>;
1719
using Vector4hp = Vector4<HighPrecisionInt>;
1820
using Matrix3hp = Matrix3<HighPrecisionInt>;
1921
using Matrix4hp = Matrix4<HighPrecisionInt>;

source/MRMesh/MRPrecisePredicates2.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "MRPrecisePredicates2.h"
22
#include "MRHighPrecision.h"
33
#include "MRGTest.h"
4+
#include "MRPrecisePredicates3.h"
45

56
namespace MR
67
{
@@ -68,6 +69,22 @@ bool ccw( const PreciseVertCoords2* vs )
6869
return odd != ccw( vs[order[0]].pt, vs[order[1]].pt, vs[order[2]].pt );
6970
}
7071

72+
bool inCircle( const std::array<PreciseVertCoords2, 4>& vs )
73+
{
74+
return inCircle( vs.data() );
75+
}
76+
77+
bool inCircle( const PreciseVertCoords2* vs )
78+
{
79+
PreciseVertCoordsll vs3d[4];
80+
for ( int i = 0; i < 4; ++i )
81+
{
82+
vs3d[i].id = vs[i].id;
83+
vs3d[i].pt = Vector3ll( Vector3ll::ValueType( vs[i].pt.x ) * vs[i].pt.x + Vector3ll::ValueType( vs[i].pt.y ) * vs[i].pt.y, vs[i].pt.x, vs[i].pt.y );
84+
}
85+
return ccw( vs ) == orient3d( vs3d ); // TODO: looks like orient3d is not "honest" enough for this predicate
86+
}
87+
7188
SegmentSegmentIntersectResult doSegmentSegmentIntersect( const std::array<PreciseVertCoords2, 4> & vs )
7289
{
7390
SegmentSegmentIntersectResult res;
@@ -192,4 +209,51 @@ TEST( MRMesh, PrecisePredicates2more )
192209
EXPECT_TRUE( ccw( { vs[2],vs[3],vs[0] } ) );
193210
}
194211

212+
TEST( MRMesh, PrecisePredicates2InCircle )
213+
{
214+
std::array<PreciseVertCoords2, 4> vs =
215+
{
216+
PreciseVertCoords2{ 3_v, Vector2i{ -1, 2 } },
217+
PreciseVertCoords2{ 2_v, Vector2i( 0 , 0 ) },
218+
PreciseVertCoords2{ 0_v, Vector2i{ 3, 10 } },
219+
PreciseVertCoords2{ 1_v, Vector2i{ 0 , 0 } }
220+
};
221+
EXPECT_TRUE( ccw( { vs[0],vs[1],vs[2] } ) );
222+
223+
// These 3 proves that vs[3] is inside vs[0]vs[1]vs[2] triangle
224+
EXPECT_TRUE( ccw( { vs[0],vs[1],vs[3] } ) );
225+
EXPECT_TRUE( ccw( { vs[1],vs[2],vs[3] } ) );
226+
EXPECT_TRUE( ccw( { vs[2],vs[0],vs[3] } ) );
227+
228+
// Check that vs[3] is inCircle
229+
EXPECT_TRUE( inCircle( vs ) );
230+
}
231+
232+
TEST( MRMesh, PrecisePredicates2InCircle2 )
233+
{
234+
std::array<PreciseVertCoords2, 5> vs =
235+
{
236+
PreciseVertCoords2{ 0_v, Vector2i{ -106280744 , -1002263723 } },
237+
PreciseVertCoords2{ 1_v, Vector2i( -187288916 , -172107608 ) },
238+
PreciseVertCoords2{ 2_v, Vector2i{ -25334363 , -1063004405 } },
239+
PreciseVertCoords2{ 3_v, Vector2i{ -15200618 , -10122159 } },
240+
PreciseVertCoords2{ 4_v, Vector2i{ -106280744 , -1002263723 } }
241+
};
242+
243+
// Prove that 0_v 2_v 4_v circle is in +Y half plane (4_v 2_v is horde in lower part)
244+
EXPECT_FALSE( ccw( { vs[2],vs[4],vs[3] } ) ); // 3_v is to the right of 2-4 vec
245+
246+
// looks like this should be false
247+
EXPECT_TRUE( inCircle( { vs[4],vs[2],vs[0],vs[3] } ) ); // 3_v is in circle
248+
249+
// prove that 0_v is inside 142 triangle
250+
EXPECT_TRUE( ccw( { vs[1],vs[4],vs[0] } ) );
251+
EXPECT_TRUE( ccw( { vs[4],vs[2],vs[0] } ) );
252+
EXPECT_TRUE( ccw( { vs[2],vs[1],vs[0] } ) );
253+
// it means that 142 circle should be larger in +Y half plane and so 3_v should be inside it
254+
// but it is not
255+
// DISABLED
256+
//EXPECT_TRUE( inCircle( { vs[1],vs[4],vs[2],vs[3] } ) );
257+
}
258+
195259
} //namespace MR

source/MRMesh/MRPrecisePredicates2.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ namespace MR
1111
/// \ingroup MathGroup
1212
/// \{
1313

14+
struct PreciseVertCoord
15+
{
16+
VertId id; ///< unique id of the vertex (in both contours)
17+
int pt; ///< coordinate
18+
};
19+
20+
/// return true if l is smaller then r
21+
/// uses simulation-of-simplicity to avoid "number are the same"
22+
inline bool smaller( const PreciseVertCoord& l, const PreciseVertCoord& r )
23+
{ return l.pt < r.pt || ( l.pt == r.pt && r.id < l.id ); }
24+
1425
/// return true if the smallest rotation from vector (a) to vector (b) is in counter-clock-wise direction;
1526
/// uses simulation-of-simplicity to avoid "vectors are collinear"
1627
MRMESH_API bool ccw( const Vector2i & a, const Vector2i & b );
@@ -30,6 +41,10 @@ struct PreciseVertCoords2
3041
MRMESH_API bool ccw( const std::array<PreciseVertCoords2, 3> & vs );
3142
MRMESH_API bool ccw( const PreciseVertCoords2* vs );
3243

44+
/// return true if 4th point in array lays inside circumcircle of first 3 points based triangle
45+
MRMESH_API bool inCircle( const std::array<PreciseVertCoords2, 4>& vs );
46+
MRMESH_API bool inCircle( const PreciseVertCoords2* vs );
47+
3348
struct SegmentSegmentIntersectResult
3449
{
3550
bool doIntersect = false; ///< whether the segments intersect

source/MRMesh/MRPrecisePredicates3.cpp

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,40 @@ constexpr double cRangeIntMax = 0.99 * std::numeric_limits<int>::max(); // 0.99
1313
namespace MR
1414
{
1515

16-
bool orient3d( const Vector3i & a, const Vector3i & b, const Vector3i & c )
16+
template<typename T, typename hT, typename hhT>
17+
bool orient3dT( const Vector3<T> & a, const Vector3<T>& b, const Vector3<T>& c )
1718
{
18-
auto vhp = mixed( Vector3hp{ a }, Vector3hp{ b }, Vector3hp{ c } );
19+
auto vhp = mixed( Vector3<hhT>{ a }, Vector3<hhT>{ b }, Vector3<hhT>{ c } );
1920
if ( vhp ) return vhp > 0;
2021

21-
auto v = cross( Vector2ll{ b.x, b.y }, Vector2ll{ c.x, c.y } );
22+
auto v = cross( Vector2<hT>{ b.x, b.y }, Vector2<hT>{ c.x, c.y } );
2223
if ( v ) return v > 0;
2324

24-
v = -cross( Vector2ll{ b.x, b.z }, Vector2ll{ c.x, c.z } );
25+
v = -cross( Vector2<hT>{ b.x, b.z }, Vector2<hT>{ c.x, c.z } );
2526
if ( v ) return v > 0;
2627

27-
v = cross( Vector2ll{ b.y, b.z }, Vector2ll{ c.y, c.z } );
28+
v = cross( Vector2<hT>{ b.y, b.z }, Vector2<hT>{ c.y, c.z } );
2829
if ( v ) return v > 0;
2930

30-
v = -cross( Vector2ll{ a.x, a.y }, Vector2ll{ c.x, c.y } );
31+
v = -cross( Vector2<hT>{ a.x, a.y }, Vector2<hT>{ c.x, c.y } );
3132
if ( v ) return v > 0;
3233

3334
if ( c.x ) return c.x > 0;
3435

3536
if ( c.y ) return c.y < 0;
3637

37-
v = cross( Vector2ll{ a.x, a.z }, Vector2ll{ c.x, c.z } );
38+
v = cross( Vector2<hT>{ a.x, a.z }, Vector2<hT>{ c.x, c.z } );
3839
if ( v ) return v > 0;
3940

4041
if ( c.z ) return c.z > 0;
4142

4243
#ifndef NDEBUG
43-
v = -cross( Vector2ll{ a.y, a.z }, Vector2ll{ c.y, c.z } );
44+
v = -cross( Vector2<hT>{ a.y, a.z }, Vector2<hT>{ c.y, c.z } );
4445
assert( v == 0 );
4546
if ( v ) return v > 0;
4647
#endif
4748

48-
v = cross( Vector2ll{ a.x, a.y }, Vector2ll{ b.x, b.y } );
49+
v = cross( Vector2<hT>{ a.x, a.y }, Vector2<hT>{ b.x, b.y } );
4950
if ( v ) return v > 0;
5051

5152
if ( b.x ) return b.x < 0;
@@ -57,15 +58,21 @@ bool orient3d( const Vector3i & a, const Vector3i & b, const Vector3i & c )
5758
return true;
5859
}
5960

60-
bool orient3d( const std::array<PreciseVertCoords, 4> & vs )
61+
bool orient3d( const Vector3i& a, const Vector3i& b, const Vector3i& c )
6162
{
62-
return orient3d( vs.data() );
63+
return orient3dT<int, long long, HighPrecisionInt>( a, b, c );
6364
}
6465

65-
bool orient3d( const PreciseVertCoords* vs )
66+
bool orient3d( const Vector3ll& a, const Vector3ll& b, const Vector3ll& c )
67+
{
68+
return orient3dT<long long, HighPrecisionInt, HighHighPrecisionInt>( a, b, c );
69+
}
70+
71+
template<typename T>
72+
bool orient3dT( const T* vs )
6673
{
6774
bool odd = false;
68-
std::array<int, 4> order = {0, 1, 2, 3};
75+
std::array<int, 4> order = { 0, 1, 2, 3 };
6976

7077
for ( int i = 0; i < 3; ++i )
7178
{
@@ -83,6 +90,26 @@ bool orient3d( const PreciseVertCoords* vs )
8390
return odd != orient3d( vs[order[0]].pt, vs[order[1]].pt, vs[order[2]].pt, vs[order[3]].pt );
8491
}
8592

93+
bool orient3d( const std::array<PreciseVertCoords, 4> & vs )
94+
{
95+
return orient3dT( vs.data() );
96+
}
97+
98+
bool orient3d( const PreciseVertCoords* vs )
99+
{
100+
return orient3dT( vs );
101+
}
102+
103+
bool orient3d( const std::array<PreciseVertCoordsll, 4>& vs )
104+
{
105+
return orient3dT( vs.data() );
106+
}
107+
108+
bool orient3d( const PreciseVertCoordsll* vs )
109+
{
110+
return orient3dT( vs );
111+
}
112+
86113
TriangleSegmentIntersectResult doTriangleSegmentIntersect( const std::array<PreciseVertCoords, 5> & vs )
87114
{
88115
TriangleSegmentIntersectResult res;

source/MRMesh/MRPrecisePredicates3.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,32 @@ namespace MR
1414
/// returns true if the plane with orientated triangle ABC has 0 point at the left;
1515
/// uses simulation-of-simplicity to avoid "0 is exactly on plane"
1616
MRMESH_API bool orient3d( const Vector3i & a, const Vector3i & b, const Vector3i & c );
17+
MRMESH_API bool orient3d( const Vector3ll& a, const Vector3ll& b, const Vector3ll& c );
1718

1819
/// returns true if the plane with orientated triangle ABC has D point at the left;
1920
/// uses simulation-of-simplicity to avoid "D is exactly on plane"
2021
inline bool orient3d( const Vector3i & a, const Vector3i & b, const Vector3i & c, const Vector3i & d )
2122
{ return orient3d( a - d, b - d, c - d ); }
23+
inline bool orient3d( const Vector3ll & a, const Vector3ll & b, const Vector3ll & c, const Vector3ll & d )
24+
{ return orient3d( a - d, b - d, c - d ); }
2225

2326
struct PreciseVertCoords
2427
{
2528
VertId id; ///< unique id of the vertex (in both meshes)
2629
Vector3i pt; ///< integer coordinates of the vertex
2730
};
2831

32+
struct PreciseVertCoordsll
33+
{
34+
VertId id; ///< unique id of the vertex (in both meshes)
35+
Vector3ll pt; ///< integer coordinates of the vertex
36+
};
37+
2938
/// first sorts the indices in ascending order, then calls the predicate for sorted points
3039
MRMESH_API bool orient3d( const std::array<PreciseVertCoords, 4> & vs );
3140
MRMESH_API bool orient3d( const PreciseVertCoords* vs );
41+
MRMESH_API bool orient3d( const std::array<PreciseVertCoordsll, 4>& vs );
42+
MRMESH_API bool orient3d( const PreciseVertCoordsll* vs );
3243

3344
struct TriangleSegmentIntersectResult
3445
{

0 commit comments

Comments
 (0)