MeshLib C++ Docs
Loading...
Searching...
No Matches
MRIntersection.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRPlane3.h"
4#include "MRLine3.h"
5#include "MRLineSegm.h"
6#include "MRVector2.h"
7#include "MRBox.h"
8#include "MRSphere.h"
9#include <optional>
10
11namespace MR
12{
13
17
21template<typename T>
22std::optional<Line3<T>> intersection( const Plane3<T>& plane1, const Plane3<T>& plane2,
23 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
24{
25 const auto crossDir = cross( plane1.n, plane2.n );
26
27 if ( crossDir.lengthSq() < errorLimit * errorLimit )
28 return {};
29
30 Matrix3<T> matrix( plane1.n, plane2.n, crossDir );
31 const auto point = matrix.inverse() * Vector3<T>( plane1.d, plane2.d, 0 );
32
33 return Line3<T>( point, crossDir.normalized() );
34}
35
39template<typename T>
40std::optional<Vector3<T>> intersection( const Plane3<T>& plane, const Line3<T>& line,
41 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
42{
43 const auto den = dot( plane.n, line.d );
44 if ( std::abs(den) < errorLimit )
45 return {};
46 return line.p + ( plane.d - dot( plane.n, line.p ) ) / den * line.d;
47}
48
52template<typename T>
53std::optional<Vector3<T>> intersection( const Line3<T>& line1, const Line3<T>& line2,
54 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
55{
56 const auto crossDir = cross( line1.d, line2.d );
57 if ( crossDir.lengthSq() < errorLimit * errorLimit )
58 return {};
59
60 const auto p1 = dot( crossDir, line1.p );
61 const auto p2 = dot( crossDir, line2.p );
62 if ( std::abs( p1 - p2 ) >= errorLimit )
63 return {};
64
65 const auto n2 = cross( line2.d, crossDir );
66 const T den = dot( line1.d, n2 );
67 if ( den == 0 )
68 return {};
69 return line1.p + dot( ( line2.p - line1.p ), n2 ) / den * line1.d;
70}
71
74inline std::optional<Vector2f> intersection( const LineSegm2f& segm1, const LineSegm2f& segm2 )
75{
76 auto avec = segm1.b - segm1.a;
77 if ( cross( avec, segm2.a - segm1.a ) * cross( segm2.b - segm1.a, avec ) <= 0 )
78 return {};
79 auto bvec = segm2.b - segm2.a;
80 auto cda = cross( bvec, segm1.a - segm2.a );
81 auto cbd = cross( segm1.b - segm2.a, bvec );
82 if ( cda * cbd <= 0 )
83 return {};
84 return ( segm1.b * cda + segm1.a * cbd ) / ( cda + cbd );
85}
86
89template<typename T>
90std::optional<T> distanceSq( const Plane3<T>& plane1, const Plane3<T>& plane2,
91 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
92{
93 const auto crossDir = cross( plane1.n, plane2.n );
94
95 if ( crossDir.lengthSq() >= errorLimit * errorLimit )
96 return {};
97
98 return ( plane2.n * plane2.d - plane1.n * plane1.d ).lengthSq();
99}
100
103template<typename T>
104std::optional<T> distance( const Plane3<T>& plane1, const Plane3<T>& plane2,
105 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
106{
107 std::optional<T> res = distanceSq( plane1, plane2, errorLimit );
108 if ( res )
109 *res = std::sqrt( *res );
110 return res;
111}
112
115template<typename T>
116std::optional<T> distance( const Plane3<T>& plane, const Line3<T>& line,
117 T errorLimit = std::numeric_limits<T>::epsilon() * T( 20 ) )
118{
119 const auto den = dot( plane.n, line.d );
120 if ( std::abs( den ) >= errorLimit )
121 return {};
122
123 return std::abs( dot( line.p, plane.n ) - plane.d );
124}
125
130template<typename T>
131std::pair<T,T> closestPointsParams( const Line3<T>& line1, const Line3<T>& line2 )
132{
133 const auto d11 = line1.d.lengthSq();
134 const auto d12 = dot( line1.d, line2.d );
135 const auto d22 = line2.d.lengthSq();
136 const auto det = d12 * d12 - d11 * d22;
137 if ( det == 0 )
138 {
140 return { T(0), line2.projectionParam( line1.p ) };
141 }
142
143 const auto dp = line2.p - line1.p;
144 const auto x = dot( dp, line1.d ) / det;
145 const auto y = dot( dp, line2.d ) / det;
146 const auto a = d12 * y - d22 * x;
147 const auto b = d11 * y - d12 * x;
148 return { a, b };
149}
150
154template<typename T>
155LineSegm3<T> closestPoints( const Line3<T>& line1, const Line3<T>& line2 )
156{
157 const auto pp = closestPointsParams( line1, line2 );
158 return { line1( pp.first ), line2( pp.second ) };
159}
160
164template<typename T>
166{
167 const auto d11 = ln.d.lengthSq();
168 const auto d12 = dot( ln.d, ls.dir() );
169 const auto d22 = ls.lengthSq();
170 const auto det = d12 * d12 - d11 * d22;
171 if ( det == 0 )
172 return { ln.project( ls.a ), ls.a };
173
174 const auto dp = ls.a - ln.p;
175 const auto x = dot( dp, ln.d ) / det;
176 const auto y = dot( dp, ls.dir() ) / det;
177 const auto b = d11 * y - d12 * x;
178 if ( b <= 0 )
179 return { ln.project( ls.a ), ls.a };
180 if ( b >= 1 )
181 return { ln.project( ls.b ), ls.b };
182 const auto a = d12 * y - d22 * x;
183 return { ln( a ), ls( b ) };
184}
185
187template<typename T>
188LineSegm3<T> closestPoints( const Line3<T>& line, const Box3<T> & box )
189{
190 LineSegm3<T> res;
191 const auto dd = line.d.lengthSq();
192 if ( dd <= 0 )
193 {
194 res.a = line.p;
195 res.b = box.getBoxClosestPointTo( res.a );
196 return res;
197 }
198 const auto rdd = 1 / dd;
199
200 T bestDistSq = std::numeric_limits<T>::max();
201
202 static constexpr int otherDir[3][2] = { { 1, 2 }, { 2, 0 }, { 0, 1 } };
203 for ( int iDir = 0; iDir < 3; ++iDir )
204 {
206 Vector3<T> q[4] = { box.min, box.min, box.min, box.min };
207 {
208 const int iDir1 = otherDir[iDir][0];
209 const int iDir2 = otherDir[iDir][1];
210
211 q[1][iDir2] = box.max[iDir2];
212
213 q[2][iDir1] = box.max[iDir1];
214 q[2][iDir2] = box.max[iDir2];
215
216 q[3][iDir1] = box.max[iDir1];
217 }
218
219 const auto e = box.max[iDir] - box.min[iDir];
220 const auto ee = e * e;
221 const auto db = line.d[iDir] * e;
222 const auto denom = dd * ee - db * db;
223 const bool par = denom <= 0;
224 const auto rdenom = par ? 0 : 1 / denom;
225 for ( int j = 0; j < 4; ++j )
226 {
227 LineSegm3<T> cand;
228 if ( par )
229 {
230 cand.a = line.p;
231 cand.a[iDir] = q[j][iDir];
232 cand.b = q[j];
233 }
234 else
235 {
236 const auto s = q[j] - line.p;
237 const auto dt = dot( line.d, s );
238 const auto bt = s[iDir] * e;
239
241 const auto t = ( dt * ee - bt * db ) * rdenom;
242 assert( !std::isnan( t ) );
243
245 const auto u = ( t * db - bt ) / ee;
246 assert( !std::isnan( u ) );
247
248 if ( u <= 0 )
249 {
250 cand.a = line( dt * rdd );
251 cand.b = q[j];
252 }
253 else if ( u >= 1 )
254 {
255 cand.a = line( ( db + dt ) * rdd );
256 cand.b = q[j];
257 cand.b[iDir] = box.max[iDir];
258 }
259 else
260 {
261 cand.a = line( t );
262 cand.b = q[j];
263 cand.b[iDir] += e * u;
264 }
265 }
266 const auto distSq = cand.lengthSq();
267 if ( distSq < bestDistSq )
268 {
269 bestDistSq = distSq;
270 res = cand;
271 }
272 }
273 }
274 return res;
275}
276
279template<typename V>
280auto intersection( const Line<V>& line, const Sphere<V>& sphere )
281{
282 using T = typename V::ValueType;
283 std::optional<std::pair<T,T>> res;
284 const auto p = line.p - sphere.center;
285 const auto d = line.d;
286 const auto dd = dot( d, d );
287 const auto pd = dot( p, d );
288 const auto des4 = sqr( pd ) - dd * ( dot( p, p ) - sqr( sphere.radius ) );
289 if ( des4 < 0 )
290 return res;
291 const auto sqrtDes4 = std::sqrt( des4 );
292 res.emplace();
293 res->first = ( -sqrtDes4 - pd ) / dd;
294 res->second = ( sqrtDes4 - pd ) / dd;
295 return res;
296}
297
299
300}
LineSegm2f
Definition MRMeshFwd.h:340
constexpr T sqr(T x) noexcept
squared value
Definition MRMeshFwd.h:761
LineSegm< Vector3< T > > LineSegm3
Definition MRMeshFwd.h:346
T projectionParam(const V &x) const
finds the parameter of the closest point to the given one on this line
Definition MRLine.h:43
Box< Vector3< T > > Box3
Definition MRMeshFwd.h:419
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
V a
Definition MRLineSegm.h:17
Vector3< T > n
Definition MRPlane3.h:22
Line< Vector3< T > > Line3
Definition MRMeshFwd.h:337
V d
Definition MRLine.h:19
T lengthSq() const
returns squared length of this line segment
Definition MRLineSegm.h:26
T d
Definition MRPlane3.h:23
V center
Definition MRSphere.h:17
V dir() const
returns directional vector of the line
Definition MRLineSegm.h:24
T radius
Definition MRSphere.h:18
V p
Definition MRLine.h:19
V project(const V &x) const
finds the closest point to the given one on this line
Definition MRLine.h:46
V b
Definition MRLineSegm.h:17
std::optional< Line3< T > > intersection(const Plane3< T > &plane1, const Plane3< T > &plane2, T errorLimit=std::numeric_limits< T >::epsilon() *T(20))
Definition MRIntersection.h:22
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< T > distance(const Plane3< T > &plane1, const Plane3< T > &plane2, T errorLimit=std::numeric_limits< T >::epsilon() *T(20))
Definition MRIntersection.h:104
LineSegm3< T > closestPoints(const Line3< T > &line1, const Line3< T > &line2)
Definition MRIntersection.h:155
std::pair< T, T > closestPointsParams(const Line3< T > &line1, const Line3< T > &line2)
Definition MRIntersection.h:131
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
V getBoxClosestPointTo(const V &pt) const
returns closest point in the box to given point
Definition MRBox.h:160
V max
Definition MRBox.h:35
V min
Definition MRBox.h:35
Definition MRLine.h:16
Definition MRMatrix3.h:24
Definition MRPlane3.h:21
Definition MRSphere.h:14
T cross(const Vector2< T > &a, const Vector2< T > &b)
cross product
Definition MRVector2.h:160
Definition MRVector3.h:33