MeshLib C++ Docs
Loading...
Searching...
No Matches
MRTriangleIntersection.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRVector3.h"
5#include "MRTriPoint.h"
6#include "MRTriMath.h"
7#include "MRLineSegm.h"
8
9#include <algorithm>
10#include <optional>
11
12namespace MR
13{
14
18
20{
24 float t = 0;
25 TriIntersectResult(float U, float V, float dist)
26 {
27 bary.a = U; bary.b = V; t = dist;
28 }
29};
30
33template <typename T>
35{
36 const auto ab2 = distanceSq( a, b );
37 const auto bc2 = distanceSq( b, c );
38 const auto ca2 = distanceSq( c, a );
39 if ( ab2 >= bc2 && ab2 >= ca2 )
40 return;
41
42 if ( bc2 >= ca2 )
43 {
44 assert( bc2 >= ab2 );
45 auto t = a;
46 a = b;
47 b = c;
48 c = t;
49 return;
50 }
51
52 assert( ca2 >= ab2 );
53 assert( ca2 >= bc2 );
54 auto t = a;
55 a = c;
56 c = b;
57 b = t;
58}
59
64template <typename T>
68)
69{
70 if ( dirDblArea( a, b, c ) == Vector3<T>{} )
71 {
72 rotateToLongestEdge( a, b, c );
73 return doTriangleSegmentIntersect( d, e, f, a, b );
74 }
75 if ( dirDblArea( d, e, f ) == Vector3<T>{} )
76 {
77 rotateToLongestEdge( d, e, f );
78 return doTriangleSegmentIntersect( a, b, c, d, e );
79 }
80
81 const auto abcd = mixed( a - d, b - d, c - d );
82 const auto abce = mixed( a - e, b - e, c - e );
83 const auto abcf = mixed( a - f, b - f, c - f );
84 const auto abc_de = abcd * abce >= 0;
85 const auto abc_fd = abcf * abcd >= 0;
86
87 if ( abc_de && abc_fd && abce * abcf >= 0 )
88 return false;
89
90 const auto defa = mixed( d - a, e - a, f - a );
91 const auto defb = mixed( d - b, e - b, f - b );
92 const auto defc = mixed( d - c, e - c, f - c );
93 const auto def_ab = defa * defb >= 0;
94 const auto def_ca = defc * defa >= 0;
95
96 if ( def_ab && def_ca && defb * defc >= 0 )
97 return false;
98
99 if ( abc_de )
100 std::swap( d, f );
101 else if( abc_fd )
102 std::swap( d, e );
104
105 if ( def_ab )
106 std::swap( a, c );
107 else if ( def_ca )
108 std::swap( a, b );
110
111 const auto abde = mixed( a - e, b - e, d - e );
112 const auto abdf = mixed( a - f, b - f, d - f );
113
114 if ( abde * abdf < 0 )
115 return true;
116
117 const auto acde = mixed( a - e, c - e, d - e );
118
119 if ( abde * acde < 0 )
120 return true;
121
122 if ( abdf == 0 && acde == 0 )
123 return true;
124
125 const auto acdf = mixed( a - f, c - f, d - f );
126
127 if ( acde * acdf < 0 )
128 return true;
129
130 if ( abdf * acdf < 0 )
131 return true;
132
133 if ( abde == 0 && acdf == 0 )
134 return true;
135
136 return false;
137}
138
140template<typename T>
141bool isPointInPlane( const Vector3<T>& p, const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& c )
142{
143 return mixed( p - a, p - b, p - c ) == T( 0 );
144}
145
146MR_BIND_TEMPLATE( bool isPointInPlane( const Vector3<float>& p, const Vector3<float>& a, const Vector3<float>& b, const Vector3<float>& c ) )
147MR_BIND_TEMPLATE( bool isPointInPlane( const Vector3<double>& p, const Vector3<double>& a, const Vector3<double>& b, const Vector3<double>& c ) )
148
149
150template<typename T>
151bool isPointInLine( const Vector3<T>& p, const Vector3<T>& a, const Vector3<T>& b )
152{
153 return cross( p - a, p - b ).lengthSq() == T( 0 );
154}
155
157template<typename T>
158bool isPointInLine( const Vector2<T>& p, const Vector2<T>& a, const Vector2<T>& b )
159{
160 return cross( p - a, p - b ) == T( 0 );
161}
162
164template<typename T>
165bool isPointInSegm( const Vector3<T>& p, const Vector3<T>& a, const Vector3<T>& b )
166{
167 if ( !isPointInLine( p, a, b ) )
168 return false;
169
170 return dot( p - a, b - a ) >= 0 && dot( p - b, a - b ) >= 0;
171}
172
174template<typename T>
175bool isPointInSegm( const Vector2<T>& p, const Vector2<T>& a, const Vector2<T>& b )
176{
177 if ( !isPointInLine( p, a, b ) )
178 return false;
179
180 return dot( p - a, b - a ) >= 0 && dot( p - b, a - b ) >= 0;
181}
182
183MR_BIND_TEMPLATE( bool isPointInLine( const Vector3<float>& p, const Vector3<float>& a, const Vector3<float>& b ) )
184MR_BIND_TEMPLATE( bool isPointInLine( const Vector3<double>& p, const Vector3<double>& a, const Vector3<double>& b ) )
185MR_BIND_TEMPLATE( bool isPointInSegm( const Vector3<float>& p, const Vector3<float>& a, const Vector3<float>& b ) )
186MR_BIND_TEMPLATE( bool isPointInSegm( const Vector3<double>& p, const Vector3<double>& a, const Vector3<double>& b ) )
187
188
189template<typename T>
190bool isPointInTriangle( const Vector3<T>& p, const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& c )
191{
192 if ( !isPointInPlane( p, a, b, c ) )
193 return false;
194 const auto normDir = cross( b - a, c - a );
195 if ( dot( normDir, cross( b - a, p - a ) ) < 0 )
196 return false;
197 if ( dot( normDir, cross( c - b, p - b ) ) < 0 )
198 return false;
199 if ( dot( normDir, cross( a - c, p - c ) ) < 0 )
200 return false;
201 if ( normDir.lengthSq() == 0 )
202 {
203
205 if ( a == b && b == c && p != a )
206 return false;
207 if ( dot( b - a, c - a ) <= 0 )
208 return isPointInSegm( p, b, c );
209 else if ( ( b - a ).lengthSq() > ( c - a ).lengthSq() )
210 return isPointInSegm( p, a, b );
211 else
212 return isPointInSegm( p, a, c );
213 }
214 return true;
215}
216
218template<typename T>
219bool isPointInTriangle( const Vector2<T>& p, const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& c )
220{
221 const auto normSign = cross( b - a, c - a );
222 if ( normSign * cross( b - a, p - a ) < 0 )
223 return false;
224 if ( normSign * cross( c - b, p - b ) < 0 )
225 return false;
226 if ( normSign * cross( a - c, p - c ) < 0 )
227 return false;
228 if ( normSign == 0 )
229 {
231 if ( a == b && b == c && p != a )
232 return false;
233 if ( dot( b - a, c - a ) <= 0 )
234 return isPointInSegm( p, b, c );
235 else if ( ( b - a ).lengthSq() > ( c - a ).lengthSq() )
236 return isPointInSegm( p, a, b );
237 else
238 return isPointInSegm( p, a, c );
239 }
240
241 return true;
242}
243
244MR_BIND_TEMPLATE( bool isPointInTriangle( const Vector3<float>& p, const Vector3<float>& a, const Vector3<float>& b, const Vector3<float>& c ) )
245MR_BIND_TEMPLATE( bool isPointInTriangle( const Vector3<double>& p, const Vector3<double>& a, const Vector3<double>& b, const Vector3<double>& c ) )
246MR_BIND_TEMPLATE( bool isPointInTriangle( const Vector2<float>& p, const Vector2<float>& a, const Vector2<float>& b, const Vector2<float>& c ) )
247MR_BIND_TEMPLATE( bool isPointInTriangle( const Vector2<double>& p, const Vector2<double>& a, const Vector2<double>& b, const Vector2<double>& c ) )
248
249
250template <typename T>
252 const Vector3<T> & x, const Vector3<T> & y, const Vector3<T> & z,
253 const Vector3<T> & u, const Vector3<T> & v, const Vector3<T> & w,
254 Vector3<T> d
255)
256{
257 const auto xy = ( y - x ).normalized();
258 d = ( d - xy * dot( xy, d ) ).normalized();
260 const auto dz = dot( d, z - x );
261 return
262 dz * dot( d, u - x ) < 0 &&
263 dz * dot( d, v - x ) < 0 &&
264 dz * dot( d, w - x ) < 0;
265}
266
271template <typename T>
273 const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c,
274 const Vector3<T> & d, const Vector3<T> & e, const Vector3<T> & f
275)
276{
277 if ( !doTrianglesIntersect( a, b, c, d, e, f ) )
278 return false;
279
281 const auto dir = a + b + c - d - e - f;
282
283 return
284 !doesEdgeXySeparate( a, b, c, d, e, f, dir ) &&
285 !doesEdgeXySeparate( b, c, a, d, e, f, dir ) &&
286 !doesEdgeXySeparate( c, a, b, d, e, f, dir ) &&
287 !doesEdgeXySeparate( d, e, f, a, b, c, dir ) &&
288 !doesEdgeXySeparate( e, f, d, a, b, c, dir ) &&
289 !doesEdgeXySeparate( f, d, e, a, b, c, dir );
290}
291
293template <typename T>
295 const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c,
296 const Vector3<T> & d, const Vector3<T> & e
297)
298{
299 const auto dabe = mixed( d - e, a - e, b - e );
300 const auto dbce = mixed( d - e, b - e, c - e );
301 if ( dabe * dbce <= 0 )
302 return false;
303
304 const auto dcae = mixed( d - e, c - e, a - e );
305 if ( dbce * dcae <= 0 )
306 return false;
307
308 if ( dcae * dabe <= 0 )
309 return false;
310
311 return true;
312}
313
315template <typename T>
317 const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c,
318 const Vector3<T> & d, const Vector3<T> & e
319)
320{
321 const auto abcd = mixed( a - d, b - d, c - d );
322 const auto abce = mixed( a - e, b - e, c - e );
323 if ( abcd * abce >= 0 )
324 return false;
325 return doTriangleLineIntersect( a, b, c, d, e );
326}
327
329template <typename T>
331 const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& c,
332 const Vector3<T>& d, const Vector3<T>& e
333)
334{
335 const auto abcd = std::abs( mixed( a - d, b - d, c - d ) );
336 const auto abce = std::abs( mixed( a - e, b - e, c - e ) );
337 auto r = std::clamp( abcd / ( abcd + abce ), T( 0 ), T( 1 ) );
338 return r * e + ( 1 - r ) * d;
339}
340
343template <typename T>
344std::optional<Vector3<T>> findTriangleTriangleIntersection(
345 const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& c,
346 const Vector3<T>& d, const Vector3<T>& e, const Vector3<T>& f )
347{
348 if ( doTriangleSegmentIntersect( a, b, c, d, e ) )
349 return findTriangleSegmentIntersection( a, b, c, d, e );
350 if ( doTriangleSegmentIntersect( a, b, c, e, f ) )
351 return findTriangleSegmentIntersection( a, b, c, e, f );
352 if ( doTriangleSegmentIntersect( a, b, c, f, d ) )
353 return findTriangleSegmentIntersection( a, b, c, f, d );
354
355 if ( doTriangleSegmentIntersect( d, e, f, a, b ) )
356 return findTriangleSegmentIntersection( d, e, f, a, b );
357 if ( doTriangleSegmentIntersect( d, e, f, b, c ) )
358 return findTriangleSegmentIntersection( d, e, f, b, c );
359 if ( doTriangleSegmentIntersect( d, e, f, c, a ) )
360 return findTriangleSegmentIntersection( d, e, f, c, a );
361 return std::nullopt;
362}
363
364template <typename T>
365std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<T>& oriA, const Vector3<T>& oriB, const Vector3<T>& oriC,
366 const IntersectionPrecomputes<T>& prec )
367{
368 const T& Sx = prec.Sx;
369 const T& Sy = prec.Sy;
370 const T& Sz = prec.Sz;
371
372 const T Ax = oriA[prec.idxX] - Sx * oriA[prec.maxDimIdxZ];
373 const T Ay = oriA[prec.idxY] - Sy * oriA[prec.maxDimIdxZ];
374 const T Bx = oriB[prec.idxX] - Sx * oriB[prec.maxDimIdxZ];
375 const T By = oriB[prec.idxY] - Sy * oriB[prec.maxDimIdxZ];
376 const T Cx = oriC[prec.idxX] - Sx * oriC[prec.maxDimIdxZ];
377 const T Cy = oriC[prec.idxY] - Sy * oriC[prec.maxDimIdxZ];
378
380 const T eps = std::numeric_limits<T>::epsilon() * std::max( { Ax, Bx, Cx, Ay, By, Cy } );
381 T U = Cx * By - Cy * Bx;
382 T V = Ax * Cy - Ay * Cx;
383 T W = Bx * Ay - By * Ax;
384
385 if( U < -eps || V < -eps || W < -eps )
386 {
387 if( U > eps || V > eps || W > eps )
388 {
390 return std::nullopt;
391 }
392 }
393
394 T det = U + V + W;
395 if( det == T( 0 ) )
396 return std::nullopt;
397 const T Az = Sz * oriA[prec.maxDimIdxZ];
398 const T Bz = Sz * oriB[prec.maxDimIdxZ];
399 const T Cz = Sz * oriC[prec.maxDimIdxZ];
400 const T t = U * Az + V * Bz + W * Cz;
401
402 auto invDet = T( 1 ) / det;
403 return TriIntersectResult( float( V * invDet ), float( W * invDet ), float( t * invDet ) );
404}
405
406MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<float >& oriA, const Vector3<float >& oriB, const Vector3<float >& oriC, const IntersectionPrecomputes<float >& prec ) )
407MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<double>& oriA, const Vector3<double>& oriB, const Vector3<double>& oriC, const IntersectionPrecomputes<double>& prec ) )
408
409template <typename T>
410std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<T>& oriA, const Vector3<T>& oriB, const Vector3<T>& oriC,
411 const Vector3<T>& dir )
412{
413 const IntersectionPrecomputes<T> prec( dir );
414 return rayTriangleIntersect( oriA, oriB, oriC, prec );
415}
416
417MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<float >& oriA, const Vector3<float >& oriB, const Vector3<float >& oriC, const Vector3<float >& dir ) )
418MR_BIND_TEMPLATE( std::optional<TriIntersectResult> rayTriangleIntersect( const Vector3<double>& oriA, const Vector3<double>& oriB, const Vector3<double>& oriC, const Vector3<double>& dir ) )
419
420
421template<typename T>
422bool doTrianglesOverlap( const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& c, const Vector2<T>& d, const Vector2<T>& e, const Vector2<T>& f )
423{
425
428 return true;
430 return true;
432 return true;
433
436 return true;
438 return true;
440 return true;
441
444 return true;
446 return true;
448 return true;
449
452 if ( isPointInTriangle( a, d, e, f ) )
453 return true;
454 if ( isPointInTriangle( d, a, b, c ) )
455 return true;
456
457 return false;
458}
459
460MR_BIND_TEMPLATE( bool doTrianglesOverlap( const Vector2<float>& a, const Vector2<float>& b, const Vector2<float>& c, const Vector2<float>& d, const Vector2<float>& e, const Vector2<float>& f ) )
461MR_BIND_TEMPLATE( bool doTrianglesOverlap( const Vector2<double>& a, const Vector2<double>& b, const Vector2<double>& c, const Vector2<double>& d, const Vector2<double>& e, const Vector2<double>& f ) )
462
463
464
465}
int idxY
Definition MRIntersectionPrecomputes.h:124
T Sx
precomputed factors
Definition MRIntersectionPrecomputes.h:130
int idxX
Definition MRIntersectionPrecomputes.h:123
T Sz
Definition MRIntersectionPrecomputes.h:130
T Sy
Definition MRIntersectionPrecomputes.h:130
int maxDimIdxZ
Definition MRIntersectionPrecomputes.h:122
TriPointf
Definition MRMeshFwd.h:497
auto dot(const Matrix2< T > &a, const Matrix2< T > &b) -> decltype(dot(a.x, b.x))
double-dot product: x = a : b
Definition MRMatrix2.h:142
TriangleSegmentIntersectResult doTriangleSegmentIntersect(const std::array< PreciseVertCoords, 5 > &vs)
Vector3f dirDblArea(const MeshTopology &topology, const VertCoords &points, FaceId f)
computes directed double area for a triangular face from its vertices
Definition MRMeshMath.h:153
MRMESH_CLASS Vector2
Definition MRMeshFwd.h:204
T mixed(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
mixed product
Definition MRVector3.h:208
bool doSegmentsIntersect(const LineSegm< V > &x, const LineSegm< V > &y, typename V::ValueType *xPos=nullptr, typename V::ValueType *yPos=nullptr)
Definition MRLineSegm.h:56
MRMESH_CLASS Vector3
Definition MRMeshFwd.h:218
std::optional< T > distanceSq(const Plane3< T > &plane1, const Plane3< T > &plane2, T errorLimit=std::numeric_limits< T >::epsilon() *T(20))
Definition MRIntersection.h:90
std::optional< Vector3< T > > findTriangleTriangleIntersection(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, const Vector3< T > &d, const Vector3< T > &e, const Vector3< T > &f)
Definition MRTriangleIntersection.h:344
bool isPointInPlane(const Vector3< T > &p, const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
returns true if ABC plane contains point P
Definition MRTriangleIntersection.h:141
void rotateToLongestEdge(Vector3< T > &a, Vector3< T > &b, Vector3< T > &c)
Definition MRTriangleIntersection.h:34
bool doTrianglesIntersect(Vector3< T > a, Vector3< T > b, Vector3< T > c, Vector3< T > d, Vector3< T > e, Vector3< T > f)
Definition MRTriangleIntersection.h:65
std::optional< TriIntersectResult > rayTriangleIntersect(const Vector3< T > &oriA, const Vector3< T > &oriB, const Vector3< T > &oriC, const IntersectionPrecomputes< T > &prec)
Definition MRTriangleIntersection.h:365
bool doesEdgeXySeparate(const Vector3< T > &x, const Vector3< T > &y, const Vector3< T > &z, const Vector3< T > &u, const Vector3< T > &v, const Vector3< T > &w, Vector3< T > d)
returns true if a plane containing edge XY separates point Z from triangle UVW
Definition MRTriangleIntersection.h:251
bool isPointInTriangle(const Vector3< T > &p, const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
returns true if ABC triangle contains point P
Definition MRTriangleIntersection.h:190
bool doTriangleLineIntersect(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, const Vector3< T > &d, const Vector3< T > &e)
checks whether triangle ABC and infinite line DE intersect
Definition MRTriangleIntersection.h:294
Vector3< T > findTriangleSegmentIntersection(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, const Vector3< T > &d, const Vector3< T > &e)
this function input should have intersection
Definition MRTriangleIntersection.h:330
bool doTrianglesIntersectExt(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, const Vector3< T > &d, const Vector3< T > &e, const Vector3< T > &f)
Definition MRTriangleIntersection.h:272
bool doTrianglesOverlap(const Vector2< T > &a, const Vector2< T > &b, const Vector2< T > &c, const Vector2< T > &d, const Vector2< T > &e, const Vector2< T > &f)
returns true if ABC and DEF overlaps or touches
Definition MRTriangleIntersection.h:422
bool isPointInLine(const Vector3< T > &p, const Vector3< T > &a, const Vector3< T > &b)
returns true if AB line contains point P
Definition MRTriangleIntersection.h:151
bool isPointInSegm(const Vector3< T > &p, const Vector3< T > &a, const Vector3< T > &b)
returns true if AB segment contains point P
Definition MRTriangleIntersection.h:165
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRIntersectionPrecomputes.h:117
a segment of straight dimensional line
Definition MRLineSegm.h:15
Definition MRTriangleIntersection.h:20
TriIntersectResult(float U, float V, float dist)
Definition MRTriangleIntersection.h:25
float t
distance from ray origin to p in dir length units
Definition MRTriangleIntersection.h:24
TriPointf bary
barycentric representation
Definition MRTriangleIntersection.h:22
Definition MRVector2.h:29
T cross(const Vector2< T > &a, const Vector2< T > &b)
cross product
Definition MRVector2.h:160
Definition MRVector3.h:33