Fix for Line_3 Ray_3 do_intersect (#8398)

## Summary of Changes

Some non intersection is wrongfully detected as an intersection for the
Line_3 Ray_3 combination. Here is an illustration:


![image](https://github.com/user-attachments/assets/f18fd662-5ad6-4a01-9a49-a8d0c62cf7fe)

The base code is :
```cpp
  if(!do_intersect(l, r.supporting_line()))
    return false;

  typename K::Coplanar_orientation_3 pred = k.coplanar_orientation_3_object();
  CGAL::Orientation p0p1s = pred(l.point(0), l.point(1), r.source());
  if(p0p1s == COLLINEAR)
    return true;

  CGAL::Orientation stp0 = pred(r.source(), r.second_point(), l.point(0));
  if(stp0 == COLLINEAR)
    return Ray_3_has_on_collinear_Point_3(r,l.point(0),k);

  return (p0p1s != stp0);
```

The supporting line of the ray intersects the line, and then nothing is
collinear, so we check L0,L1,R1 vs R0,R1,L0, which are of opposite sign
so there is an intersection... but there is none.

This check is very similar to what is done in Ray_3-Ray_3, where it is
correct.

I did a naive fix for now: without loss of generality we can go to the
configuration below


![image](https://github.com/user-attachments/assets/5f004941-7f58-4bf3-8416-7dc2144a891f)

and so we have an intersection as long as the ray "points" in the other
slab wrt to the line. And so, in coplanar orientation checks, if the
orientation L0,L1,R0 differs from L0, L1, (L0 + (R1-R0)).

I feel like I could probably skip at least a translation by having
something like Coplanar_orientation(P3, P3, P3, V3), and maybe even
more...

## Release Management

* Affected package(s): `Intersections_3`
* Issue(s) solved (if any): -
* Feature/Small Feature (if any): -
* License and copyright ownership: no change
This commit is contained in:
Sebastien Loriot 2024-08-26 15:21:21 +02:00 committed by GitHub
commit 9dea168da5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 5 deletions

View File

@ -38,11 +38,8 @@ do_intersect(const typename K::Line_3& l,
if(p0p1s == COLLINEAR)
return true;
CGAL::Orientation stp0 = pred(r.source(), r.second_point(), l.point(0));
if(stp0 == COLLINEAR)
return Ray_3_has_on_collinear_Point_3(r,l.point(0),k);
return (p0p1s != stp0);
typename K::Point_3 lst = l.point(0) + (r.point(1) - r.point(0));
return (pred(l.point(0), l.point(1), r.point(0), lst) != CGAL::POSITIVE);
}
template <class K>

View File

@ -232,6 +232,10 @@ public:
check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(3,0,1),p(6,0,1)));
check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(0,2,0),p(0,4,0)));
check_no_intersection(L(p(0,0,0),p(1,0,0)), R(p(6,2,0),p(5,4,0)));
check_no_intersection(L(p(0,0,0),p(0,1,0)), R(p(1,-1,0),p(1,0,0)));
check_no_intersection(L(p(0,-10,0),p(0,-9,0)), R(p(1,-1,0),p(2,0,0)));
check_no_intersection(L(p(0,-10,0),p(0,0,0)), R(p(1,-1,0),p(2,0,0)));
check_no_intersection(L(p(0,0,0),p(0,1,0)), R(p(1,-1,0),p(2,0,0)));
// Point intersection
check_intersection (L(p(0,0,0),p(1,0,0)), R(p(3,0,0),p(6,4,0)),

View File

@ -74,6 +74,14 @@ public:
check_no_intersection (R(p(0,0,0), p(1,0,0)), R(p(0,1,0), p(0,2,0)));
check_no_intersection (R(p(0,0,0), p(1,0,0)), R(p(-1,0,0), p(-1,-1,0)));
check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,0,0)));
check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,-1,0)));
check_no_intersection (R(p(1,-1,0), p(2,0,0)), R(p(2,-1,0), p(3,-2,0)));
check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(0,-1,0), p(1,-1,0)));
check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(-1,-3,0),p(2,0,0)));
check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(-2,-4,0),p(-1,-3,0)));
check_no_intersection (R(p(0,0,0), p(0,1,0)), R(p(1,-1,0), p(2,0,0)));
// Point
check_intersection (R(p(0,0,0), p(1,0,0)), R(p(0,0,0), p(-1,0,0)),
p(0,0,0));
@ -88,6 +96,10 @@ public:
check_intersection (R(p(0,0,0), p(1,0,0)), R(p(1,-2,0), p(1,-1,0)),
p(1,0,0));
check_intersection (R(p(0,0,0), p(1,0,0)), R(p(1,-2,0), p(1,-1,0)),
p(1,0,0));
// Segment
check_intersection (R(p(0,0,0), p(1,0,0)), R(p(2,0,0), p(-3,0,0)),
S(p(0,0,0), p(2,0,0)), false);