线段相交、数值稳定测试

发布于 2024-12-25 17:06:57 字数 2024 浏览 6 评论 0原文

我需要对二维中的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

颜漓半夏 2025-01-01 17:06:58

这似乎是一个非常常见的数学问题。 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

帅冕 2025-01-01 17:06:58
if(fabs(denom) < eps){
    if((fabs(len(x2, y2, x3, y3) + len(x2, y2, x4, y4) - len(x3, y3, x4, y4)) < eps) || (fabs(len(x1, y1, x3, y3) + len(x1, y1, x4, y4) - len(x3, y3, x4, y4)) < eps) || (fabs(len(x3, y3, x1, y1) + len(x3, y3, x2, y2) - len(x1, y1, x2, y2)) < eps) || (fabs(len(x4, y4, x1, y1) + len(x4, y4, x2, y2) - len(x1, y1, x2, y2)) < eps)){
      return 1;
    }else{
      return 0;
    }
}

其中 len = sqrt(sqr(c - a) + sqr(d - b))

if(fabs(denom) < eps){
    if((fabs(len(x2, y2, x3, y3) + len(x2, y2, x4, y4) - len(x3, y3, x4, y4)) < eps) || (fabs(len(x1, y1, x3, y3) + len(x1, y1, x4, y4) - len(x3, y3, x4, y4)) < eps) || (fabs(len(x3, y3, x1, y1) + len(x3, y3, x2, y2) - len(x1, y1, x2, y2)) < eps) || (fabs(len(x4, y4, x1, y1) + len(x4, y4, x2, y2) - len(x1, y1, x2, y2)) < eps)){
      return 1;
    }else{
      return 0;
    }
}

Where len = sqrt(sqr(c - a) + sqr(d - b))

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文