mirror of https://github.com/CGAL/cgal
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:
commit
38812be5eb
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue