MeshLib C++ Docs
Loading...
Searching...
No Matches
MRLineSegm.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMeshFwd.h"
4#include "MRVector2.h"
5
6namespace MR
7{
8
9// a segment of straight dimensional line
10template <typename V>
12{
13 using T = typename V::ValueType;
14 V a, b;
15
16 [[nodiscard]] constexpr LineSegm() noexcept = default;
17 [[nodiscard]] constexpr LineSegm( const V & a, const V & b ) noexcept : a( a ), b( b ) { }
18 template <typename U>
19 [[nodiscard]] constexpr explicit LineSegm( const LineSegm<U> & p ) noexcept : a( p.a ), b( p.b ) { }
21 [[nodiscard]] V dir() const { return b - a; }
23 [[nodiscard]] T lengthSq() const { return dir().lengthSq(); }
25 [[nodiscard]] T length() const { return dir().length(); }
27 [[nodiscard]] V operator()( T param ) const { return ( 1 - param ) * a + param * b; }
28};
29
30template <typename V>
31[[nodiscard]] inline bool operator == ( const LineSegm<V> & a, const LineSegm<V> & b )
32{
33 return a.a == b.a && a.b == b.b;
34}
35
36template <typename V>
37[[nodiscard]] V closestPointOnLineSegm( const V& pt, const LineSegm<V> & l )
38{
39 auto ab = l.b - l.a;
40 auto dt = dot( pt - l.a, ab );
41 auto abLengthSq = ab.lengthSq();
42 if ( dt <= 0 )
43 return l.a;
44 if ( dt >= abLengthSq )
45 return l.b;
46 auto ratio = dt / abLengthSq;
47 return l.a * ( 1 - ratio ) + l.b * ratio;
48}
49
52template <typename V>
53[[nodiscard]] bool doSegmentsIntersect( const LineSegm<V> & x, const LineSegm<V> & y,
54 typename V::ValueType * xPos = nullptr, typename V::ValueType * yPos = nullptr )
55{
56 // check whether infinite line x intersect segment y
57 const auto xvec = x.b - x.a;
58 const auto ya = cross( xvec, y.a - x.a );
59 const auto yb = cross( xvec, y.b - x.a );
60 if ( ya * yb > 0 )
61 return false;
62
63 // check whether infinite line y intersect segment x
64 const auto yvec = y.b - y.a;
65 const auto xa = cross( yvec, x.a - y.a );
66 const auto xb = cross( yvec, x.b - y.a );
67 if ( xa * xb > 0 )
68 return false;
69
70 // degenerate cases
71 if ( cross( xvec, yvec ) == 0 )
72 {
73 // on the same line
74 if ( xvec != V() )
75 {
76 if ( dot( xvec, y.a - x.a ) * dot( xvec, y.b - x.a ) > 0 &&
77 dot( -xvec, y.a - x.b ) * dot( -xvec, y.b - x.b ) > 0 )
78 return false; // segments does not overlap
79 }
80 else if ( yvec != V() )
81 {
82 if ( dot( yvec, x.a - y.a ) * dot( yvec, x.b - y.a ) > 0 &&
83 dot( -yvec, x.a - y.b ) * dot( -yvec, x.b - y.b ) > 0 )
84 return false; // segments does not overlap
85 }
86 else if ( x.a != y.a )
87 return false; // fully degenerated
88 }
89
90 if ( xPos )
91 {
92 // calculates intersection position on segment x
93 const auto denom = xa - xb;
94 *xPos = denom == 0 ? 0 : xa / denom;
95 }
96 if ( yPos )
97 {
98 // calculates intersection position on segment y
99 const auto denom = ya - yb;
100 *yPos = denom == 0 ? 0 : ya / denom;
101 }
102 return true;
103}
104
107template <typename V>
108[[nodiscard]] bool doSegmentLineIntersect( const LineSegm<V> & x, const Line<V> & y,
109 typename V::ValueType * xPos = nullptr, typename V::ValueType * yPos = nullptr )
110{
111 // check whether infinite line y intersect segment x
112 const auto xa = cross( y.d, x.a - y.p );
113 const auto xb = cross( y.d, x.b - y.p );
114
115 // if several line segments are connected in polyline, this ensures that only one of them will be intersected,
116 // even is the line passes exactly through segment's end
117 if ( ( xa <= 0 ) == ( xb <= 0 ) )
118 return false; // both ends of the segment are at the same side of the line
119
120 if ( xPos )
121 {
122 // calculates intersection position on segment x
123 const auto denom = xa - xb;
124 *xPos = denom == 0 ? 0 : xa / denom;
125 }
126 if ( yPos )
127 {
128 // calculates intersection position on line y
129 const auto xvec = x.b - x.a;
130 const auto ya = cross( xvec, y.p - x.a );
131 const auto yb = cross( xvec, y.p + y.d - x.a );
132
133 const auto denom = ya - yb;
134 *yPos = denom == 0 ? 0 : ya / denom;
135 }
136 return true;
137}
138
139MR_BIND_TEMPLATE( bool doSegmentsIntersect( const LineSegm<Vector2<float>>& x, const LineSegm<Vector2<float>>& y, float* xPos, float* yPos ) )
140MR_BIND_TEMPLATE( bool doSegmentsIntersect( const LineSegm<Vector2<double>>& x, const LineSegm<Vector2<double>>& y, double* xPos, double* yPos ) )
141
142MR_BIND_TEMPLATE( bool doSegmentLineIntersect( const LineSegm<Vector2<float>>& x, const Line<Vector2<float>>& y, float* xPos, float* yPos ) )
143MR_BIND_TEMPLATE( bool doSegmentLineIntersect( const LineSegm<Vector2<double>>& x, const Line<Vector2<double>>& y, double* xPos, double* yPos ) )
144
145} //namespace MR
MRMESH_API bool operator==(const BitSet &a, const BitSet &b)
compare that two bit sets have the same set bits (they can be equal even if sizes are distinct but la...
Definition MRCameraOrientationPlugin.h:8
V closestPointOnLineSegm(const V &pt, const LineSegm< V > &l)
Definition MRLineSegm.h:37
bool doSegmentLineIntersect(const LineSegm< V > &x, const Line< V > &y, typename V::ValueType *xPos=nullptr, typename V::ValueType *yPos=nullptr)
Definition MRLineSegm.h:108
bool doSegmentsIntersect(const LineSegm< V > &x, const LineSegm< V > &y, typename V::ValueType *xPos=nullptr, typename V::ValueType *yPos=nullptr)
Definition MRLineSegm.h:53
Definition MRLineSegm.h:12
constexpr LineSegm() noexcept=default
T length() const
returns the length of this line segment
Definition MRLineSegm.h:25
typename V::ValueType T
Definition MRLineSegm.h:13
V a
Definition MRLineSegm.h:14
constexpr LineSegm(const LineSegm< U > &p) noexcept
Definition MRLineSegm.h:19
T lengthSq() const
returns squared length of this line segment
Definition MRLineSegm.h:23
V operator()(T param) const
returns point on the line, where param=0 returns a and param=1 returns b
Definition MRLineSegm.h:27
V dir() const
returns directional vector of the line
Definition MRLineSegm.h:21
V b
Definition MRLineSegm.h:14
Definition MRLine.h:13
V d
Definition MRLine.h:16
V p
Definition MRLine.h:16