Merge pull request #5680 from afabri/Intersections-fix_RT-GF

Intersections_3: Fix do_intersect(sphere/triangle) if FT has no division
This commit is contained in:
Laurent Rineau 2021-05-27 19:12:35 +02:00
commit 38812be5eb
7 changed files with 357 additions and 129 deletions

View File

@ -26,6 +26,7 @@
#include <CGAL/Weighted_point_3.h> #include <CGAL/Weighted_point_3.h>
#include <CGAL/Vector_3.h> #include <CGAL/Vector_3.h>
#include <CGAL/number_utils.h> #include <CGAL/number_utils.h>
#include <CGAL/Rational_traits.h>
namespace CGAL { namespace CGAL {
@ -187,6 +188,21 @@ squared_distance(const typename K::Point_3 & pt1,
return k.compute_squared_distance_3_object()(pt1, pt2); return k.compute_squared_distance_3_object()(pt1, pt2);
} }
template <class K>
void
squared_distance_to_plane_RT(const typename K::Vector_3 & normal,
const typename K::Vector_3 & diff,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::RT RT;
RT dot, squared_length;
dot = wdot(normal, diff, k);
squared_length = wdot(normal, normal, k);
num = square(dot);
den = wmult((K*)0, squared_length, diff.hw(), diff.hw());
}
template <class K> template <class K>
typename K::FT typename K::FT
@ -196,13 +212,24 @@ squared_distance_to_plane(const typename K::Vector_3 & normal,
{ {
typedef typename K::RT RT; typedef typename K::RT RT;
typedef typename K::FT FT; typedef typename K::FT FT;
RT dot, squared_length; RT num, den;
dot = wdot(normal, diff, k); squared_distance_to_plane_RT(normal, diff, num, den, k);
squared_length = wdot(normal, normal, k); return Rational_traits<FT>().make_rational(num, den);
return FT(dot*dot) /
FT(wmult((K*)0, squared_length, diff.hw(), diff.hw()));
} }
template <class K>
void
squared_distance_to_line_RT(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
Vector_3 wcr = wcross(dir, diff, k);
num = wdot(wcr, wcr, k);
den = wmult((K*)0, wdot(dir, dir, k), diff.hw(), diff.hw());
}
template <class K> template <class K>
typename K::FT typename K::FT
@ -210,15 +237,13 @@ squared_distance_to_line(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff, const typename K::Vector_3 & diff,
const K& k) const K& k)
{ {
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT; typedef typename K::RT RT;
typedef typename K::FT FT; typedef typename K::FT FT;
Vector_3 wcr = wcross(dir, diff, k); RT num, den;
return FT(wcr*wcr)/FT(wmult( squared_distance_to_line_RT(dir, diff, num, den, k);
(K*)0, RT(wdot(dir, dir, k)), diff.hw(), diff.hw())); return Rational_traits<FT>().make_rational(num, den);
} }
template <class K> template <class K>
inline inline
bool bool

View File

@ -31,17 +31,33 @@ namespace CGAL {
namespace internal { namespace internal {
template <class K> template <class K>
typename K::FT void
squared_distance( squared_distance_RT(
const typename K::Point_3 &pt, const typename K::Point_3 &pt,
const typename K::Line_3 &line, const typename K::Line_3 &line,
typename K::RT& num,
typename K::RT& den,
const K& k) const K& k)
{ {
typedef typename K::Vector_3 Vector_3; typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 construct_vector; typename K::Construct_vector_3 construct_vector;
Vector_3 dir(line.direction().vector()); Vector_3 dir(line.direction().vector());
Vector_3 diff = construct_vector(line.point(), pt); Vector_3 diff = construct_vector(line.point(), pt);
return internal::squared_distance_to_line(dir, diff, k); return internal::squared_distance_to_line_RT(dir, diff, num, den, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Point_3 &pt,
const typename K::Line_3 &line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT num, den;
squared_distance_RT(pt, line, num, den, k);
return Rational_traits<FT>().make_rational(num, den);
} }
template <class K> template <class K>
@ -56,6 +72,31 @@ squared_distance(
} }
template <class K>
void
squared_distance_RT(
const typename K::Point_3 &pt,
const typename K::Ray_3 &ray,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
Vector_3 diff = construct_vector(ray.source(), pt);
const Vector_3 &dir = ray.direction().vector();
if (!is_acute_angle(dir,diff, k) )
{
num = wdot(diff, diff, k);
den = wmult((K*)0, RT(1), diff.hw(), diff.hw());
return;
}
squared_distance_to_line_RT(dir, diff, num, den, k);
}
template <class K> template <class K>
typename K::FT typename K::FT
squared_distance( squared_distance(
@ -63,16 +104,25 @@ squared_distance(
const typename K::Ray_3 &ray, const typename K::Ray_3 &ray,
const K& k) const K& k)
{ {
typename K::Construct_vector_3 construct_vector; // This duplicates code from the _RT functions, but it is a slowdown to do something like:
//
// RT num, den;
// squared_distance_RT(pt, ray, num, den, k);
// return Rational_traits<FT>().make_rational(num, den);
//
// See https://github.com/CGAL/cgal/pull/5680
typedef typename K::Vector_3 Vector_3; typedef typename K::Vector_3 Vector_3;
Vector_3 diff = construct_vector(ray.source(), pt); typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
const Vector_3 &dir = ray.direction().vector();
if (!is_acute_angle(dir,diff, k) )
return (typename K::FT)(diff*diff);
return squared_distance_to_line(dir, diff, k);
}
Vector_3 diff = construct_vector(ray.source(), pt);
const Vector_3 &dir = ray.direction().vector();
if (!is_acute_angle(dir,diff, k) )
return (typename K::FT)(diff*diff);
return squared_distance_to_line(dir, diff, k);
}
template <class K> template <class K>
inline inline
@ -85,75 +135,77 @@ squared_distance(
return squared_distance(pt, ray, k); return squared_distance(pt, ray, k);
} }
template <class K> template <class K>
typename K::FT void
squared_distance( squared_distance_RT(
const typename K::Point_3 &pt, const typename K::Point_3 &pt,
const typename K::Segment_3 &seg, const typename K::Segment_3 &seg,
const K& k, typename K::RT& num,
const Homogeneous_tag) typename K::RT& den,
const K& k)
{ {
typename K::Construct_vector_3 construct_vector; typedef typename K::Vector_3 Vector_3;
typedef typename K::Vector_3 Vector_3; typedef typename K::RT RT;
typedef typename K::RT RT;
typedef typename K::FT FT;
// assert that the segment is valid (non zero length).
Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k);
if (d <= (RT)0)
return (FT(diff*diff));
RT e = wdot(segvec,segvec, k);
if ( (d * segvec.hw()) > (e * diff.hw()))
return squared_distance(pt, seg.target(), k);
Vector_3 wcr = wcross(segvec, diff, k); typename K::Construct_vector_3 construct_vector;
return FT(wcr*wcr)/FT(e * diff.hw() * diff.hw());
// assert that the segment is valid (non zero length).
const Vector_3 diff_s = construct_vector(seg.source(), pt);
const Vector_3 segvec = construct_vector(seg.source(), seg.target());
const RT d = wdot(diff_s, segvec, k);
if (d <= RT(0))
{
// this is squared_distance(pt, seg.source())
num = wdot(diff_s, diff_s, k);
den = wmult((K*)0, RT(1), diff_s.hw(), diff_s.hw());
return;
}
const RT e = wdot(segvec, segvec, k);
if (wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff_s.hw()))
{
// this is squared_distance(pt, seg.target())
const Vector_3 diff_t = construct_vector(seg.target(), pt);
num = wdot(diff_t, diff_t, k);
den = wmult((K*)0, RT(1), diff_t.hw(), diff_t.hw());
return;
}
// This is an expanded call to squared_distance_to_line_RT() to avoid recomputing 'e'
const Vector_3 wcr = wcross(segvec, diff_s, k);
num = wdot(wcr, wcr, k);
den = wmult((K*)0, e, diff_s.hw(), diff_s.hw());
} }
template <class K> template <class K>
typename K::FT typename K::FT
squared_distance(
const typename K::Point_3 &pt,
const typename K::Segment_3 &seg,
const K& k,
const Cartesian_tag&)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
// assert that the segment is valid (non zero length).
Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k);
if (d <= (RT)0)
return (FT(diff*diff));
RT e = wdot(segvec,segvec, k);
if (d > e)
return squared_distance(pt, seg.target(), k);
Vector_3 wcr = wcross(segvec, diff, k);
return FT(wcr*wcr)/e;
}
template <class K>
inline
typename K::FT
squared_distance( squared_distance(
const typename K::Point_3 &pt, const typename K::Point_3 &pt,
const typename K::Segment_3 &seg, const typename K::Segment_3 &seg,
const K& k) const K& k)
{ {
typedef typename K::Kernel_tag Tag; typedef typename K::Vector_3 Vector_3;
Tag tag; typedef typename K::RT RT;
return squared_distance(pt, seg, k, tag); typedef typename K::FT FT;
}
typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
// assert that the segment is valid (non zero length).
Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k);
if (d <= RT(0))
return (FT(diff*diff));
RT e = wdot(segvec,segvec, k);
if (wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return squared_distance(pt, seg.target(), k);
// This is an expanded call to squared_distance_to_line() to avoid recomputing 'e'
Vector_3 wcr = wcross(segvec, diff, k);
return FT(wcr*wcr) / wmult((K*)0, e, diff.hw(), diff.hw());
}
template <class K> template <class K>
inline inline
@ -166,8 +218,6 @@ squared_distance(
return squared_distance(pt, seg, k); return squared_distance(pt, seg, k);
} }
template <class K> template <class K>
typename K::Comparison_result typename K::Comparison_result
compare_distance_pssC3( compare_distance_pssC3(
@ -187,7 +237,7 @@ compare_distance_pssC3(
Vector_3 diff = construct_vector(seg1.source(), pt); Vector_3 diff = construct_vector(seg1.source(), pt);
Vector_3 segvec = construct_vector(seg1.source(), seg1.target()); Vector_3 segvec = construct_vector(seg1.source(), seg1.target());
RT d = wdot(diff,segvec, k); RT d = wdot(diff,segvec, k);
if (d <= (RT)0){ if (d <= RT(0)){
d1 = (FT(diff*diff)); d1 = (FT(diff*diff));
}else{ }else{
RT e = wdot(segvec,segvec, k); RT e = wdot(segvec,segvec, k);
@ -204,7 +254,7 @@ compare_distance_pssC3(
Vector_3 diff = construct_vector(seg2.source(), pt); Vector_3 diff = construct_vector(seg2.source(), pt);
Vector_3 segvec = construct_vector(seg2.source(), seg2.target()); Vector_3 segvec = construct_vector(seg2.source(), seg2.target());
RT d = wdot(diff,segvec, k); RT d = wdot(diff,segvec, k);
if (d <= (RT)0){ if (d <= RT(0)){
d2 = (FT(diff*diff)); d2 = (FT(diff*diff));
}else{ }else{
RT e = wdot(segvec,segvec, k); RT e = wdot(segvec,segvec, k);
@ -240,7 +290,7 @@ compare_distance_ppsC3(
Vector_3 diff = construct_vector(seg.source(), pt); Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target()); Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k); RT d = wdot(diff,segvec, k);
if (d <= (RT)0){ if (d <= RT(0)){
d2 = (FT(diff*diff)); d2 = (FT(diff*diff));
}else{ }else{
RT e = wdot(segvec,segvec, k); RT e = wdot(segvec,segvec, k);

View File

@ -218,6 +218,91 @@ on_left_of_triangle_edge(const typename K::Point_3 & pt,
return result; return result;
} }
template <class K>
inline void
squared_distance_to_triangle_RT(
const typename K::Point_3 & pt,
const typename K::Point_3 & t0,
const typename K::Point_3 & t1,
const typename K::Point_3 & t2,
bool & inside,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vector_3 vector;
typedef typename K::Vector_3 Vector_3;
const Vector_3 e1 = vector(t0, t1);
const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k);
if(normal == NULL_VECTOR) {
// The case normal==NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
squared_distance_RT(pt, typename K::Segment_3(t2, t0), num, den, k);
typename K::RT num2, den2;
squared_distance_RT(pt, typename K::Segment_3(t1, t2), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER) {
num = num2;
den = den2;
}
// should not be needed since at most 2 edges cover the full triangle in the degenerate case
squared_distance_RT(pt, typename K::Segment_3(t0, t1), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER){
num = num2;
den = den2;
}
return;
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01) {
squared_distance_RT(pt, typename K::Segment_3(t0, t1), num, den, k);
return;
}
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12) {
squared_distance_RT(pt, typename K::Segment_3(t1, t2), num, den, k);
return;
}
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20) {
squared_distance_RT(pt, typename K::Segment_3(t2, t0), num, den, k);
return;
}
// The projection of pt is inside the triangle
inside = true;
squared_distance_to_plane_RT(normal, vector(t0, pt), num, den, k);
}
template <class K>
void
squared_distance_RT(
const typename K::Point_3 & pt,
const typename K::Triangle_3 & t,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vertex_3 vertex;
bool inside = false;
squared_distance_to_triangle_RT(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
inside,
num,
den,
k);
}
template <class K> template <class K>
inline typename K::FT inline typename K::FT
squared_distance_to_triangle( squared_distance_to_triangle(
@ -234,31 +319,37 @@ squared_distance_to_triangle(
const Vector_3 oe3 = vector(t0, t2); const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k); const Vector_3 normal = wcross(e1, oe3, k);
if(normal != NULL_VECTOR if(normal == NULL_VECTOR) {
&& on_left_of_triangle_edge(pt, normal, t0, t1, k) // The case normal==NULL_VECTOR covers the case when the triangle
&& on_left_of_triangle_edge(pt, normal, t1, t2, k) // is colinear, or even more degenerate. In that case, we can
&& on_left_of_triangle_edge(pt, normal, t2, t0, k)) // simply take also the distance to the three segments.
{ typename K::FT d1 = squared_distance(pt, typename K::Segment_3(t2, t0), k);
// the projection of pt is inside the triangle typename K::FT d2 = squared_distance(pt, typename K::Segment_3(t1, t2), k);
inside = true;
return squared_distance_to_plane(normal, vector(t0, pt), k);
}
else {
// The case normal==NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
typename K::FT d1 = squared_distance(pt,
typename K::Segment_3(t2, t0),
k);
typename K::FT d2 = squared_distance(pt,
typename K::Segment_3(t1, t2),
k);
typename K::FT d3 = squared_distance(pt,
typename K::Segment_3(t0, t1),
k);
return (std::min)( (std::min)(d1, d2), d3); // should not be needed since at most 2 edges cover the full triangle in the degenerate case
} typename K::FT d3 = squared_distance(pt, typename K::Segment_3(t0, t1), k);
return (std::min)( (std::min)(d1, d2), d3);
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01) {
return internal::squared_distance(pt, typename K::Segment_3(t0, t1), k);
}
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12) {
return internal::squared_distance(pt, typename K::Segment_3(t1, t2), k);
}
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20) {
return internal::squared_distance(pt, typename K::Segment_3(t2, t0), k);
}
// The projection of pt is inside the triangle
inside = true;
return squared_distance_to_plane(normal, vector(t0, pt), k);
} }
template <class K> template <class K>
@ -268,7 +359,7 @@ squared_distance(
const typename K::Triangle_3 & t, const typename K::Triangle_3 & t,
const K& k) const K& k)
{ {
typename K::Construct_vertex_3 vertex; typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
bool inside = false; bool inside = false;
return squared_distance_to_triangle(pt, return squared_distance_to_triangle(pt,
vertex(t, 0), vertex(t, 0),

View File

@ -2,7 +2,9 @@ Algebraic_foundations
Distance_2 Distance_2
Distance_3 Distance_3
Installation Installation
Interval_support
Kernel_23 Kernel_23
Modular_arithmetic
Number_types Number_types
Profiling_tools Profiling_tools
STL_Extension STL_Extension

View File

@ -112,6 +112,17 @@ struct Test {
{ {
std::cout << "Point - Triangle\n"; std::cout << "Point - Triangle\n";
check_squared_distance (p(0, 1, 2), T(p(0, 0, 0), p( 2, 0, 0), p( 0, 2, 0)), 4); check_squared_distance (p(0, 1, 2), T(p(0, 0, 0), p( 2, 0, 0), p( 0, 2, 0)), 4);
T t(p(0,0,0), p(3,0,0), p(3,3,0));
check_squared_distance (p(-1, -1, 0), t, 2);
check_squared_distance (p(-1, 0, 0), t, 1);
check_squared_distance (p(0, 0, 0), t, 0);
check_squared_distance (p(1, 0, 0), t, 0);
check_squared_distance (p(4, 0, 0), t, 1);
check_squared_distance (p(1, -1, 0), t, 1);
check_squared_distance (p(1, 1, 1), t, 1);
check_squared_distance (p(1, 0, 1), t, 1);
check_squared_distance (p(0, 0, 1), t, 1);
} }
void P_Tet() void P_Tet()

View File

@ -15,7 +15,7 @@
#include <CGAL/squared_distance_3_2.h> #include <CGAL/squared_distance_3_2.h>
#include <CGAL/Intersection_traits_3.h> #include <CGAL/Intersection_traits_3.h>
#include <CGAL/Rational_traits.h>
namespace CGAL { namespace CGAL {
template <class K> template <class K>
@ -36,9 +36,15 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Sphere_3 &sp, do_intersect(const typename K::Sphere_3 &sp,
const typename K::Triangle_3 &tr, const typename K::Triangle_3 &tr,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), tr) <= sp.squared_radius(); typedef typename K::RT RT;
RT num, den;
CGAL::internal::squared_distance_RT(sp.center(), tr, num, den, k);
return ! (compare_quotients<RT>(num, den,
Rational_traits<typename K::FT>().numerator(sp.squared_radius()),
Rational_traits<typename K::FT>().denominator(sp.squared_radius())) == LARGER);
} }
template <class K> template <class K>
@ -46,18 +52,9 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Triangle_3 &tr, do_intersect(const typename K::Triangle_3 &tr,
const typename K::Sphere_3 &sp, const typename K::Sphere_3 &sp,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), tr) <= sp.squared_radius(); return do_intersect(sp, tr, k);
}
template <class K>
inline
typename K::Boolean
do_intersect(const typename K::Sphere_3 &sp,
const typename K::Line_3 &lin,
const K & /* k */)
{
return squared_distance(sp.center(), lin) <= sp.squared_radius();
} }
@ -66,9 +63,26 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Line_3 &lin, do_intersect(const typename K::Line_3 &lin,
const typename K::Sphere_3 &sp, const typename K::Sphere_3 &sp,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), lin) <= sp.squared_radius(); typedef typename K::RT RT;
RT num, den;
CGAL::internal::squared_distance_RT(sp.center(), lin, num, den, k);
return ! (compare_quotients<RT>(num, den,
Rational_traits<typename K::FT>().numerator(sp.squared_radius()),
Rational_traits<typename K::FT>().denominator(sp.squared_radius())) == LARGER);
}
template <class K>
inline
typename K::Boolean
do_intersect(const typename K::Sphere_3 &sp,
const typename K::Line_3 &lin,
const K & k)
{
return do_intersect(lin,sp,k);
} }
@ -78,9 +92,15 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Sphere_3 &sp, do_intersect(const typename K::Sphere_3 &sp,
const typename K::Ray_3 &ray, const typename K::Ray_3 &ray,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), ray) <= sp.squared_radius(); typedef typename K::RT RT;
RT num, den;
CGAL::internal::squared_distance_RT(sp.center(), ray, num, den, k);
return ! (compare_quotients<RT>(num, den,
Rational_traits<typename K::FT>().numerator(sp.squared_radius()),
Rational_traits<typename K::FT>().denominator(sp.squared_radius())) == LARGER);
} }
@ -89,9 +109,9 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Ray_3 &ray, do_intersect(const typename K::Ray_3 &ray,
const typename K::Sphere_3 &sp, const typename K::Sphere_3 &sp,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), ray) <= sp.squared_radius(); return do_intersect(sp,ray,k);
} }
template <class K> template <class K>
@ -99,9 +119,15 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Sphere_3 &sp, do_intersect(const typename K::Sphere_3 &sp,
const typename K::Segment_3 &seg, const typename K::Segment_3 &seg,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), seg) <= sp.squared_radius(); typedef typename K::RT RT;
RT num, den;
CGAL::internal::squared_distance_RT(sp.center(), seg, num, den, k);
return ! (compare_quotients<RT>(num, den,
Rational_traits<typename K::FT>().numerator(sp.squared_radius()),
Rational_traits<typename K::FT>().denominator(sp.squared_radius())) == LARGER);
} }
@ -110,9 +136,9 @@ inline
typename K::Boolean typename K::Boolean
do_intersect(const typename K::Segment_3 &seg, do_intersect(const typename K::Segment_3 &seg,
const typename K::Sphere_3 &sp, const typename K::Sphere_3 &sp,
const K & /* k */) const K & k)
{ {
return squared_distance(sp.center(), seg) <= sp.squared_radius(); return do_intersect(sp,seg,k);
} }
} // namespace internal } // namespace internal

View File

@ -161,13 +161,35 @@ struct Test {
void P_do_intersect() void P_do_intersect()
{ {
P p(0,0,0), q(1,0,0), r(2,0,0), s(10,10,10); P p(0,0,0), q(1,0,0), r(2,0,0), s(10,10,10), s2(10,10,0), s3(10,-10,-1), t(3,0,0);
Sph sph(p,1); Sph sph(p,1);
Cub cub(p,r); Cub cub(p,r);
assert(do_intersect(q,sph)); assert(do_intersect(q,sph));
assert(do_intersect(sph,q)); assert(do_intersect(sph,q));
assert(! do_intersect(s,cub)); assert(! do_intersect(s,cub));
assert(! do_intersect(cub,s)); assert(! do_intersect(cub,s));
assert(do_intersect(sph, Tr(p,q,s)));
assert(do_intersect(sph, Tr(r,q,s)));
assert(! do_intersect(sph, Tr(r,s,t)));
assert(! do_intersect(sph, Tr(s,s2,s3)));
assert(do_intersect(sph, S(p,r)));
assert(do_intersect(sph, S(q,r)));
assert(do_intersect(sph, S(s,q)));
assert(! do_intersect(sph, S(s,r)));
assert(do_intersect(sph, L(p,r)));
assert(do_intersect(sph, L(q,r)));
assert(do_intersect(sph, L(s,q)));
assert(! do_intersect(sph, L(s,r)));
assert(do_intersect(sph, R(p,r)));
assert(do_intersect(sph, R(q,r)));
assert(do_intersect(sph, R(s,q)));
assert(! do_intersect(sph, R(s,r)));
} }
@ -1265,6 +1287,7 @@ struct Test {
Bbox_L(); Bbox_L();
Bbox_R(); Bbox_R();
Bbox_Tr(); Bbox_Tr();
} }
}; };