线段相交、数值稳定测试
我需要对二维中的 2 条线段相交进行精确且数值稳定的测试。有一种可能的解决方案检测 4 个位置,请参见下面的代码。
getInters ( double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double & x_int, double & y_int )
{
3: Intersect in two end points,
2: Intersect in one end point,
1: Intersect (but not in end points)
0: Do not intersect
unsigned short code = 2;
//Initialize intersections
x_int = 0, y_int = 0;
//Compute denominator
double denom = x1 * ( y4 - y3 ) + x2 * ( y3 - y4 ) + x4 * ( y2 - y1 ) + x3 * ( y1 - y2 ) ;
//Segments are parallel
if ( fabs ( denom ) < eps)
{
//Will be solved later
}
//Compute numerators
double numer1 = x1 * ( y4 - y3 ) + x3 * ( y1 - y4 ) + x4 * ( y3 - y1 );
double numer2 = - ( x1 * ( y3 - y2 ) + x2 * ( y1 - y3 ) + x3 * ( y2 - y1 ) );
//Compute parameters s,t
double s = numer1 / denom;
double t = numer2 / denom;
//Both segments intersect in 2 end points: numerically more accurate than using s, t
if ( ( fabs (numer1) < eps) && ( fabs (numer2) < eps) ||
( fabs (numer1) < eps) && ( fabs (numer2 - denom) < eps) ||
( fabs (numer1 - denom) < eps) && ( fabs (numer2) < eps) ||
( fabs (numer1 - denom) < eps) && ( fabs (numer2 - denom) < eps) )
{
code = 3;
}
//Segments do not intersect: do not compute any intersection
else if ( ( s < 0.0 ) || ( s > 1 ) ||
( t < 0.0 ) || ( t > 1 ) )
{
return 0;
}
//Segments intersect, but not in end points
else if ( ( s > 0 ) && ( s < 1 ) && ( t > 0 ) && ( t < 1 ) )
{
code = 1;
}
//Compute intersection
x_int = x1 + s * ( x2 - x1 );
y_int = y1 + s * ( y2 - y1 );
//Segments intersect in one end point
return code;
}
我不确定所有提出的条件是否设计正确(以避免圆度误差)。
使用参数 s、t 进行测试是否有意义,还是仅用于计算交集?
我担心位置 2(线段在一个端点相交)可能无法正确检测到(最后剩下的情况没有任何条件)...
I need a precise and numerically stable test for 2 line segments intersection in 2D. There is one possible solution detecting 4 postions, see bellow the code.
getInters ( double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double & x_int, double & y_int )
{
3: Intersect in two end points,
2: Intersect in one end point,
1: Intersect (but not in end points)
0: Do not intersect
unsigned short code = 2;
//Initialize intersections
x_int = 0, y_int = 0;
//Compute denominator
double denom = x1 * ( y4 - y3 ) + x2 * ( y3 - y4 ) + x4 * ( y2 - y1 ) + x3 * ( y1 - y2 ) ;
//Segments are parallel
if ( fabs ( denom ) < eps)
{
//Will be solved later
}
//Compute numerators
double numer1 = x1 * ( y4 - y3 ) + x3 * ( y1 - y4 ) + x4 * ( y3 - y1 );
double numer2 = - ( x1 * ( y3 - y2 ) + x2 * ( y1 - y3 ) + x3 * ( y2 - y1 ) );
//Compute parameters s,t
double s = numer1 / denom;
double t = numer2 / denom;
//Both segments intersect in 2 end points: numerically more accurate than using s, t
if ( ( fabs (numer1) < eps) && ( fabs (numer2) < eps) ||
( fabs (numer1) < eps) && ( fabs (numer2 - denom) < eps) ||
( fabs (numer1 - denom) < eps) && ( fabs (numer2) < eps) ||
( fabs (numer1 - denom) < eps) && ( fabs (numer2 - denom) < eps) )
{
code = 3;
}
//Segments do not intersect: do not compute any intersection
else if ( ( s < 0.0 ) || ( s > 1 ) ||
( t < 0.0 ) || ( t > 1 ) )
{
return 0;
}
//Segments intersect, but not in end points
else if ( ( s > 0 ) && ( s < 1 ) && ( t > 0 ) && ( t < 1 ) )
{
code = 1;
}
//Compute intersection
x_int = x1 + s * ( x2 - x1 );
y_int = y1 + s * ( y2 - y1 );
//Segments intersect in one end point
return code;
}
I am not sure whether all proposed conditions are designed properly (to avoid roundness errors).
Does it make sense to use the parameters s, t for testing or use it only for the computation of an intersection?
I am afraid that position 2 (segment intersect in one end point) may not be correctly detected (last remaining situation without any condition)...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这似乎是一个非常常见的数学问题。 topcoder 上有一个很好的教程,其中包含公式,可以回答您的问题,并且可以轻松地以您想要的任何编程语言实现基础知识:线相交教程
问候,
叶夫根尼娅
This seems as a very common math problem. There's a good tutorial with formulas on topcoder that answers your question and it is easy to implement the fundamentals in whatever programming language you want: Line Intersection Tutorial
Regards,
Evgenia
其中 len = sqrt(sqr(c - a) + sqr(d - b))
Where
len = sqrt(sqr(c - a) + sqr(d - b))