ON_IntersectLineLine() returns wrong results

    ON_Line lineA({ -2.0, 0.0, 0.0 }, { 2.0, 0.0, 0.0 });
    ON_Line lineB({ 0.0, 1.0, 0.0 }, { 1.0, 2.0, 0.0 });
    double a, b;
    double tolerance = 0.0;
    bool bIntersectSegments = true;
    ON_IntersectLineLine(lineA, lineB, &a, &b, tolerance, bIntersectSegments);

The results should be a=0.5, b=0.0, but it returns a=0.25,b=0.0.
image

Hi @matsukawa,

This seems to work here:

ON_3dPoint p0(-2.0, 0.0, 0.0);
ON_3dPoint p1(2.0, 0.0, 0.0);
ON_3dPoint p2(0.0, 1.0, 0.0);
ON_3dPoint p3(1.0, 2.0, 0.0);

ON_Line lineA(p0, p1);
ON_Line lineB(p2, p3);
  
double a = ON_UNSET_VALUE;
double b = ON_UNSET_VALUE;
  
bool rc = ON_IntersectLineLine(lineA, lineB, &a, &b, 0.0, false);
if (rc)
{
  ON_3dPoint point_on_lineA = lineA.PointAt(a);
  ON_3dPoint point_on_lineB = lineB.PointAt(b);
  // TODO...
}

– Dale

bIntersectSegments = false returns correct results.
bIntersectSegments = true returns wrong results.

bIntersectSegments = false
Expected Results : a = 0.25, b = -1.0.
Returned Results : a = 0.25, b = -1.0.

bIntersectSegments = true
Expected Results : a = 0.5, b = 0.0.
Returned Results : a = 0.25, b = 0.0.

In the function of ON_IntersectLineLine(), if bIntersectSegments is true, a and b are simply clamped to 0.0~1.0.
But we need to check a closest point between the terminal point and another line.

I have fixed the code and it seems to work well.

bool ON_IntersectLineLine(
          const ON_Line& lineA, 
          const ON_Line& lineB, 
          double* a,
          double* b,
          double tolerance,
          bool bIntersectSegments
          )
{
  bool rc = ON_Intersect(lineA,lineB,a,b) ? true : false;
  if (rc)
  {
    if ( bIntersectSegments )
    {
#if 0
      if ( *a < 0.0 )
        *a = 0.0;
      else if ( *a > 1.0 )
        *a = 1.0;
      if ( *b < 0.0 )
        *b = 0.0;
      else if ( *b > 1.0 )
        *b = 1.0;
#else
      bool a0 = (*a < 0.0);
      bool a1 = (*a > 1.0);
      bool b0 = (*b < 0.0);
      bool b1 = (*b > 1.0);
      if (a0)
        lineB.ClosestPointTo(lineA.from, b);
      else if (a1)
        lineB.ClosestPointTo(lineA.to, b);
      else
        *b = std::clamp(*b, 0.0, 1.0);
      if (b0) 
        lineA.ClosestPointTo(lineB.from, a);
      else if (b1)
        lineA.ClosestPointTo(lineB.to, a);
      else
        *a = std::clamp(*a, 0.0, 1.0);
#endif
    }
    if ( tolerance > 0.0 )
    {
      rc = (lineA.PointAt(*a).DistanceTo(lineB.PointAt(*b)) <= tolerance);
    }
  }
  return rc;
}