Merge branch 'Distance_3-Add_Tri_Tri-GF-old' into Distance_3-Add_Tri_Tri-GF

This commit is contained in:
Mael Rouxel-Labbé 2021-09-02 17:26:44 +02:00
commit 8a92d51601
63 changed files with 5189 additions and 3419 deletions

View File

@ -23,6 +23,8 @@
#include <CGAL/constructions/kernel_ftC2.h>
#include <CGAL/constructions/kernel_ftC3.h>
#include <CGAL/Cartesian/solve_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
namespace CGAL {
@ -457,6 +459,103 @@ namespace CartesianKernelFunctors {
}
};
namespace internal {
template <class K>
typename K::Comparison_result
compare_distance_pssC3(const typename K::Point_3 &pt,
const typename K::Segment_3 &seg1,
const typename K::Segment_3 &seg2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Construct_vector_3 construct_vector;
FT d1=FT(0), d2=FT(0);
RT e1 = RT(1), e2 = RT(1);
// assert that the segment is valid (non zero length).
{
Vector_3 diff = construct_vector(seg1.source(), pt);
Vector_3 segvec = construct_vector(seg1.source(), seg1.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d1 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d1 = CGAL::internal::squared_distance(pt, seg1.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d1 = FT(wcr*wcr);
e1 = e;
}
}
}
{
Vector_3 diff = construct_vector(seg2.source(), pt);
Vector_3 segvec = construct_vector(seg2.source(), seg2.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d2 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d2 = CGAL::internal::squared_distance(pt, seg2.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d2 = FT(wcr*wcr);
e2 = e;
}
}
}
return CGAL::compare(d1*e2, d2*e1);
}
template <class K>
typename K::Comparison_result
compare_distance_ppsC3(const typename K::Point_3 &pt,
const typename K::Point_3 &pt2,
const typename K::Segment_3 &seg,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Construct_vector_3 construct_vector;
RT e2 = RT(1);
// assert that the segment is valid (non zero length).
FT d1 = CGAL::internal::squared_distance(pt, pt2, k);
FT d2 = FT(0);
{
Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d2 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d2 = CGAL::internal::squared_distance(pt, seg.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d2 = FT(wcr*wcr);
e2 = e;
}
}
}
return CGAL::compare(d1*e2, d2);
}
} // namespace internal
template <typename K>
class Compare_distance_3
{
@ -476,19 +575,19 @@ namespace CartesianKernelFunctors {
result_type
operator()(const Point_3& p1, const Segment_3& s1, const Segment_3& s2) const
{
return CGAL::internal::compare_distance_pssC3(p1,s1,s2, K());
return internal::compare_distance_pssC3(p1,s1,s2, K());
}
result_type
operator()(const Point_3& p1, const Point_3& p2, const Segment_3& s2) const
{
return CGAL::internal::compare_distance_ppsC3(p1,p2,s2, K());
return internal::compare_distance_ppsC3(p1,p2,s2, K());
}
result_type
operator()(const Point_3& p1, const Segment_3& s2, const Point_3& p2) const
{
return opposite(CGAL::internal::compare_distance_ppsC3(p1,p2,s2, K()));
return opposite(internal::compare_distance_ppsC3(p1,p2,s2, K()));
}
template <class T1, class T2, class T3>

View File

@ -0,0 +1,58 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_LINE_2_LINE_2_H
#define CGAL_DISTANCE_2_LINE_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Kernel/global_functions.h>
#include <CGAL/Line_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line1,
const typename K::Line_2& line2,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(internal::parallel(line1, line2, k))
return sq_dist(line1.point(), line2);
else
return FT(0);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line1,
const Line_2<K>& line2)
{
return K().compute_squared_distance_2_object()(line1, line2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_LINE_2_LINE_2_H

View File

@ -0,0 +1,89 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/enum.h>
#include <CGAL/Line_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Oriented_side side0 = line.oriented_side(triangle.vertex(0));
if(line.oriented_side(triangle.vertex(1)) != side0)
return FT(0);
if(line.oriented_side(triangle.vertex(2)) != side0)
return FT(0);
FT mindist = sq_dist(triangle.vertex(0), line);
for(int i=1; i<3; ++i)
{
FT dist = sq_dist(triangle.vertex(i), line);
if(dist < mindist)
mindist = dist;
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Line_2& line,
const K& k)
{
return internal::squared_distance(line, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(line, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(triangle, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_LINE_2_H
#define CGAL_DISTANCE_2_POINT_2_LINE_2_H
#include <CGAL/Rational_traits.h>
#include <CGAL/number_utils.h>
#include <CGAL/tags.h>
#include <CGAL/Line_2.h>
#include <CGAL/Point_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K&,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
const RT& a = line.a();
const RT& b = line.b();
const RT& w = pt.hw();
RT n = a*pt.hx() + b*pt.hy() + w*line.c();
RT d = (CGAL_NTS square(a) + CGAL_NTS square(b)) * CGAL_NTS square(w);
return Rational_traits<FT>().make_rational(CGAL_NTS square(n), d);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K&,
const Cartesian_tag&)
{
typedef typename K::FT FT;
const FT& a = line.a();
const FT& b = line.b();
FT n = a*pt.x() + b*pt.y() + line.c();
FT d = CGAL_NTS square(a) + CGAL_NTS square(b);
return CGAL_NTS square(n)/d;
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K& k)
{
typedef typename K::Kernel_tag Tag;
Tag tag;
return squared_distance(pt, line, k, tag);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, line, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(pt, line);
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(line, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_LINE_2_H

View File

@ -0,0 +1,49 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_POINT_2_H
#define CGAL_DISTANCE_2_POINT_2_POINT_2_H
#include <CGAL/Point_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_2& pt1,
const typename K::Point_2& pt2,
const K& k)
{
typename K::Vector_2 vec = k.construct_vector_2_object()(pt2, pt1);
return k.compute_squared_length_2_object()(vec);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt1,
const Point_2<K>& pt2)
{
return K().compute_squared_distance_2_object()(pt1, pt2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_POINT_2_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_RAY_2_H
#define CGAL_DISTANCE_2_POINT_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
if(!is_acute_angle(ray.direction().vector(), construct_vector(ray.source(), pt), k))
{
ind = 0;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
int ind,
const K& k)
{
if(ind == 0)
return internal::squared_distance(pt, ray.source(), k);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
Vector_2 diff = construct_vector(ray.source(), pt);
const Vector_2& dir = ray.direction().vector();
if (!is_acute_angle(dir, diff, k))
return k.compute_squared_length_2_object()(diff);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Ray_2<K>& ray)
{
return internal::squared_distance(pt, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Point_2<K>& pt)
{
return internal::squared_distance(pt, ray, K());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_RAY_2_H

View File

@ -0,0 +1,126 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H
#define CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
if(!is_acute_angle(seg.target(),seg.source(),pt, k))
{
ind = 0;
return;
}
if(!is_acute_angle(seg.source(),seg.target(),pt, k))
{
ind = 1;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
int ind,
const K& k)
{
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(ind == 0)
return sq_dist(pt, seg.source());
if(ind == 1)
return sq_dist(pt, seg.target());
return sq_dist(pt, seg.supporting_line());
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Segment_2& seg,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typedef typename K::RT RT;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_length_2 sq_length = k.compute_squared_length_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
// assert that the segment is valid (non zero length).
const Vector_2 diff = vector(seg.source(), pt);
const Vector_2 segvec = vector(seg.source(), seg.target());
const RT d = wdot(diff, segvec, k);
if(d <= RT(0))
return sq_length(diff);
const RT e = wdot(segvec,segvec, k);
if(wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return sq_dist(pt, seg.target());
return sq_dist(pt, seg.supporting_line());
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, seg, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(pt, seg);
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(seg, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H

View File

@ -0,0 +1,266 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind1,
int &ind2,
const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::Point_2 Point_2;
typename K::Left_turn_2 leftturn = k.left_turn_2_object();
const Point_2& vt0 = triangle.vertex(0);
const Point_2& vt1 = triangle.vertex(1);
const Point_2& vt2 = triangle.vertex(2);
if(leftturn(vt0, vt1, vt2)) {
if(leftturn(pt, vt1, vt0)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
if(leftturn(pt, vt2, vt1)) {
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
}
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 1;
return;
} else {
if(leftturn(pt, vt2, vt1)) {
if(!is_acute_angle(vt1, vt2, pt, k)) {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
} else {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
} else {
if(leftturn(pt, vt2, vt0)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
if(leftturn(pt, vt1, vt2)) {
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
}
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 2;
return;
} else {
if(leftturn(pt, vt1, vt2)) {
if(!is_acute_angle(vt2, vt1, pt, k)) {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
} else {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
}
}
template <class K>
typename K::FT
squared_distance_indexed(const typename K::Point_2& pt,
const typename K::Triangle_2& triangle,
int ind1, int ind2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Line_2 Line_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(ind1 == -1)
return FT(0);
if(ind2 == -1)
return sq_dist(pt, triangle.vertex(ind1));
return sq_dist(pt, Line_2{triangle.vertex(ind1), triangle.vertex(ind2)});
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Triangle_2& triangle,
const K& k)
{
int ind1, ind2;
distance_index<K>(ind1, ind2, pt, triangle, k);
return squared_distance_indexed(pt, triangle, ind1, ind2, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(pt, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(triangle, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H

View File

@ -0,0 +1,88 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_LINE_2_H
#define CGAL_DISTANCE_2_RAY_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Line_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
Vector_2 normalvec(line.a(), line.b());
Vector_2 diff = construct_vector(line.point(), ray.source());
FT sign_dist = k.compute_scalar_product_2_object()(diff, normalvec);
if(sign_dist < FT(0))
{
if(is_acute_angle(normalvec, ray.direction().vector(), k))
return FT(0);
}
else
{
if(is_obtuse_angle(normalvec, ray.direction().vector(), k))
return FT(0);
}
return (square(sign_dist) / k.compute_squared_length_2_object()(normalvec));
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Line_2& line,
const K& k)
{
return internal::squared_distance(line, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(line, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(ray, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_LINE_2_H

View File

@ -0,0 +1,115 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_RAY_2_H
#define CGAL_DISTANCE_2_RAY_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(const typename K::Vector_2& ray1dir,
const typename K::Vector_2& ray2dir,
const typename K::Vector_2& from1to2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
if(!is_acute_angle(ray1dir, from1to2, k))
{
if(!same_direction(ray1dir, ray2dir, k))
return k.compute_squared_length_2_object()(from1to2);
}
RT wcr = wcross(ray1dir, from1to2, k);
RT w = from1to2.hw();
return (square(wcr) / FT(wmult((K*)0, wdot(ray1dir, ray1dir, k), w, w)));
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2& ray1,
const typename K::Ray_2& ray2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typedef typename K::FT FT;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 ray1dir = ray1.direction().vector();
const Vector_2 ray2dir = ray2.direction().vector();
const Vector_2 diffvec = vector(ray1.source(),ray2.source());
bool crossing1, crossing2;
switch(orientation(ray1dir, ray2dir, k))
{
case COUNTERCLOCKWISE:
crossing1 = !clockwise(diffvec, ray2dir, k);
crossing2 = !counterclockwise(ray1dir, diffvec, k);
break;
case CLOCKWISE:
crossing1 = !counterclockwise(diffvec, ray2dir, k);
crossing2 = !clockwise(ray1dir, diffvec, k);
break;
default:
return ray_ray_squared_distance_parallel(ray1dir, ray2dir, diffvec,k);
}
if(crossing1)
{
if(crossing2)
return FT(0);
return sq_dist(ray2.source(), ray1);
}
else
{
if(crossing2)
{
return sq_dist(ray1.source(), ray2);
}
else
{
FT min1 = sq_dist(ray1.source(), ray2);
FT min2 = sq_dist(ray2.source(), ray1);
return (min1 < min2) ? min1 : min2;
}
}
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray1, const Ray_2<K> &ray2)
{
return K().compute_squared_distance_2_object()(ray1, ray2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_RAY_2_H

View File

@ -0,0 +1,121 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typedef typename K::Line_2 Line_2;
int ind_tr1, ind_tr2, ind_ray = 0, ind1;
distance_index<K>(ind_tr1, ind_tr2, ray.source(), triangle, k);
FT mindist = squared_distance_indexed(ray.source(), triangle, ind_tr1, ind_tr2, k);
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, ray, k);
FT dist = squared_distance_indexed(pt, ray, ind1, k);
if(dist < mindist)
{
ind_ray = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if(ind_tr2 == -1 && ind_ray != -1)
return mindist;
if(ind_tr2 != -1)
{
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2& vt1 = triangle.vertex(ind_tr1);
const Point_2& vt2 = triangle.vertex(ind_tr2);
if(clockwise(ray.direction().vector(), vt2-vt1, k))
mindist = FT(0);
}
else
{
// Check if all the triangle vertices lie
// at the same side of the segment.
const Line_2& sl = ray.supporting_line();
Oriented_side or_s = sl.oriented_side(triangle.vertex(0));
for(int i=1; i<3; ++i)
{
if(sl.oriented_side(triangle.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Ray_2& ray,
const K& k)
{
return internal::squared_distance(ray, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(ray, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(triangle, ray);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H

View File

@ -0,0 +1,129 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Segment_2_Ray_2.h>
#include <CGAL/number_utils.h>
#include <CGAL/Rational_traits.h>
#include <CGAL/Line_2.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
_sqd_to_line(const typename K::Vector_2& diff,
const typename K::RT& wcross,
const typename K::Vector_2& dir)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT numerator = CGAL_NTS square(wcross);
RT denominator = wmult((K*)0, RT(wdot(dir,dir, K())), diff.hw(), diff.hw());
return Rational_traits<FT>().make_rational(numerator, denominator);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Line_2& line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typedef typename K::Point_2 Point_2;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 linedir = line.direction().vector();
const Point_2& linepoint = line.point();
const Vector_2 startvec = vector(linepoint, seg.source());
const Vector_2 endvec = vector(linepoint, seg.target());
if(seg.source() == seg.target())
return sq_dist(seg.source(), line);
bool crossing1;
const RT c1s = wcross(linedir, startvec, k);
const RT c1e = wcross(linedir, endvec, k);
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
crossing1 = true;
else
crossing1 = (c1s == RT(0));
}
if(crossing1)
{
return FT(0);
}
else
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm <= RT(0))
return _sqd_to_line<K>(startvec, c1s, linedir);
else
return _sqd_to_line<K>(endvec, c1e, linedir);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Segment_2& seg,
const K& k)
{
return internal::squared_distance(seg, line, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(seg, line);
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(line, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H

View File

@ -0,0 +1,196 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT& startwcross,
const typename K::RT& endwcross,
const typename K::Vector_2& start,
const typename K::Vector_2& end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2& seg,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 dir1 = seg.direction().vector();
const Vector_2 dir2 = ray.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return sq_dist(seg.target(), ray.source());
}
else
{
if(!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return sq_dist(seg.source(), ray.source());
}
return sq_dist(ray.source(), seg.supporting_line());
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Orientation_2 orientation = k.orientation_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2& raydir = ray.direction().vector();
const Vector_2 startvec = vector(ray.source(), seg.source());
const Vector_2 endvec = vector(ray.source(), seg.target());
if(seg.source() == seg.target())
return internal::squared_distance(seg.source(), ray, k);
bool crossing1, crossing2;
const RT c1s = wcross(raydir, startvec, k);
const RT c1e = wcross(raydir, endvec, k);
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
{
if(c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
crossing1 = true;
}
else
{
crossing1 = (c1s == RT(0));
}
}
switch (orientation(seg.source(), seg.target(), ray.source()))
{
case LEFT_TURN:
crossing2 = right_turn(vector(seg.source(), seg.target()), raydir, k);
break;
case RIGHT_TURN:
crossing2 = left_turn(vector(seg.source(), seg.target()), raydir, k);
break;
default:
crossing2 = true;
break;
}
if(crossing1)
{
if(crossing2)
return FT(0);
return sq_dist(ray.source(), seg);
}
else
{
if(crossing2)
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm < RT(0))
{
return sq_dist(seg.source(), ray);
}
else
{
if(dm > RT(0))
return sq_dist(seg.target(), ray);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg, ray, k);
}
}
else
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
const FT min1 = (dm < RT(0)) ? sq_dist(seg.source(), ray)
: sq_dist(seg.target(), ray);
const FT min2 = sq_dist(ray.source(), seg);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Segment_2& seg,
const K& k)
{
return internal::squared_distance(seg, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(seg, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(ray, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H

View File

@ -0,0 +1,351 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Segment_2.h>
#include <CGAL/number_utils.h>
#include <CGAL/tags.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 dir1 = seg1.direction().vector();
const Vector_2 dir2 = seg2.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return sq_dist(seg1.target(), seg2.source());
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return sq_dist(seg1.source(), seg2.target());
}
else
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return sq_dist(seg1.target(), seg2.target());
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return sq_dist(seg1.source(), seg2.source());
}
return sq_dist(seg2.source(), seg1.supporting_line());
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT& startwcross,
const typename K::RT& endwcross,
const typename K::Point_2& start,
const typename K::Point_2& end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k,
const Cartesian_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Orientation_2 orientation = k.orientation_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(seg1.source() == seg1.target())
return sq_dist(seg1.source(), seg2);
if(seg2.source() == seg2.target())
return sq_dist(seg2.source(), seg1);
const Orientation o1s = orientation(seg2.source(), seg2.target(), seg1.source());
const Orientation o1e = orientation(seg2.source(), seg2.target(), seg1.target());
bool crossing1, crossing2;
if(o1s == RIGHT_TURN)
{
crossing1 = (o1e != RIGHT_TURN);
}
else
{
if(o1e != LEFT_TURN)
{
if(o1s == COLLINEAR && o1e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
}
else
{
crossing1 = (o1s == COLLINEAR);
}
}
const Orientation o2s = orientation(seg1.source(), seg1.target(), seg2.source());
const Orientation o2e = orientation(seg1.source(), seg1.target(), seg2.target());
if(o2s == RIGHT_TURN)
{
crossing2 = (o2e != RIGHT_TURN);
}
else
{
if(o2e != LEFT_TURN)
{
if(o2s == COLLINEAR && o2e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
}
else
{
crossing2 = (o2s == COLLINEAR);
}
}
if(crossing1)
{
if(crossing2)
return (FT)0;
const RT c2s = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
const RT c2e = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
Comparison_result dm = CGAL_NTS compare(c2s, c2e);
if(dm == SMALLER)
{
return sq_dist(seg2.source(), seg1);
}
else
{
if(dm == LARGER)
{
return sq_dist(seg2.target(), seg1);
}
else
{
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
}
else
{
const RT c1s = CGAL_NTS abs(wcross(seg2.source(), seg2.target(), seg1.source(), k));
const RT c1e = CGAL_NTS abs(wcross(seg2.source(), seg2.target(), seg1.target(), k));
Comparison_result dm = CGAL_NTS compare(c1s, c1e);
if(crossing2)
{
if(dm == SMALLER)
{
return sq_dist(seg1.source(), seg2);
}
else
{
if(dm == LARGER)
return sq_dist(seg1.target(), seg2);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
if(dm == EQUAL)
return internal::squared_distance_parallel(seg1, seg2, k);
FT min1 = (dm == SMALLER) ? sq_dist(seg1.source(), seg2):
sq_dist(seg1.target(), seg2);
const RT c2s = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
const RT c2e = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
dm = CGAL_NTS compare(c2s,c2e);
if(dm == EQUAL) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
FT min2 = (dm == SMALLER) ? sq_dist(seg2.source(), seg1):
sq_dist(seg2.target(), seg1);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(seg1.source() == seg1.target())
return sq_dist(seg1.source(), seg2);
if(seg2.source() == seg2.target())
return sq_dist(seg2.source(), seg1);
const RT c1s = wcross(seg2.source(), seg2.target(), seg1.source(), k);
const RT c1e = wcross(seg2.source(), seg2.target(), seg1.target(), k);
const RT c2s = wcross(seg1.source(), seg1.target(), seg2.source(), k);
const RT c2e = wcross(seg1.source(), seg1.target(), seg2.target(), k);
bool crossing1, crossing2;
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
{
if(c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
}
else
{
crossing1 = (c1s == RT(0));
}
}
if(c2s < RT(0))
{
crossing2 = (c2e >= RT(0));
}
else
{
if(c2e <= RT(0))
{
if(c2s == RT(0) && c2e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
}
else
{
crossing2 = (c2s == RT(0));
}
}
if(crossing1)
{
if(crossing2)
return (FT)0;
const RT dm = _distance_measure_sub<K>(c2s,c2e, seg2.source(), seg2.target());
if(dm < RT(0))
{
return sq_dist(seg2.source(), seg1);
}
else
{
if(dm > RT(0))
return sq_dist(seg2.target(), seg1);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
if(crossing2)
{
const RT dm = _distance_measure_sub<K>(c1s, c1e,seg1.source(),seg1.target());
if(dm < RT(0))
{
return sq_dist(seg1.source(), seg2);
}
else
{
if(dm > RT(0))
return sq_dist(seg1.target(), seg2);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
RT dm = _distance_measure_sub<K>(c1s, c1e, seg1.source(), seg1.target());
if(dm == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
FT min1 = (dm < RT(0)) ? sq_dist(seg1.source(), seg2):
sq_dist(seg1.target(), seg2);
dm = _distance_measure_sub<K>(c2s, c2e, seg2.source(), seg2.target());
if(dm == RT(0)) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
FT min2 = (dm < RT(0)) ? sq_dist(seg2.source(), seg1):
sq_dist(seg2.target(), seg1);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg1,
const Segment_2<K>& seg2,
const K& k)
{
typedef typename K::Kernel_tag Tag;
return squared_distance(seg1, seg2, k, Tag());
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg1,
const Segment_2<K>& seg2)
{
return K().compute_squared_distance_2_object()(seg1, seg2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H

View File

@ -0,0 +1,136 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation = k.orientation_2_object();
int i, ind_tr1 = 0, ind_tr2 = -1, ind_seg = 0, ind1, ind2;
FT dist;
FT mindist = internal::squared_distance(seg.source(), triangle.vertex(0), k);
for(i=0; i<2; ++i)
{
const Point_2& pt = seg.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle, k);
dist = internal::squared_distance_indexed(pt, triangle, ind1, ind2, k);
if(dist < mindist)
{
ind_seg = i;
ind_tr1 = ind1; ind_tr2 = ind2;
mindist = dist;
}
}
for(i=0; i<3; ++i)
{
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, seg, k);
dist = internal::squared_distance_indexed(pt, seg, ind1, k);
if(dist < mindist)
{
ind_seg = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if(ind_tr2 == -1 && ind_seg != -1)
return mindist;
if(ind_tr2 != -1)
{
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
const Orientation or_s = orientation(vt1, vt2, seg.source());
if(orientation(vt1, vt2, seg.target()) != or_s)
mindist = FT(0);
}
else
{
// Check if all the triangle vertices lie
// at the same side of the segment.
const Point_2& vt1 = seg.source();
const Point_2& vt2 = seg.target();
const Orientation or_s = orientation(vt1, vt2, triangle.vertex(0));
for(i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Segment_2 & seg,
const K& k)
{
return internal::squared_distance(seg, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(seg, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(triangle, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H

View File

@ -0,0 +1,123 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Triangle_2& triangle1,
const typename K::Triangle_2& triangle2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation = k.orientation_2_object();
int ind1_1 = 0, ind1_2 = -1, ind2_1 = 0, ind2_2 = -1, ind1, ind2;
FT dist;
FT mindist = internal::squared_distance(triangle1.vertex(0), triangle2.vertex(0), k);
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle1.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle2, k);
dist = squared_distance_indexed(pt, triangle2, ind1, ind2, k);
if(dist < mindist)
{
ind1_1 = i; ind1_2 = -1;
ind2_1 = ind1; ind2_2 = ind2;
mindist = dist;
}
}
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle2.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle1, k);
dist = squared_distance_indexed(pt, triangle1, ind1, ind2, k);
if(dist < mindist)
{
ind1_1 = ind1; ind1_2 = ind2;
ind2_1 = i; ind2_2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
if(ind1_2 == -1 && ind2_2 == -1)
return mindist;
// In case of point-segment closest distance, there is still the
// possibility of overlapping triangles. Check if all the
// vertices lie at the same side of the segment.
if(ind1_2 != -1)
{
const Point_2& vt1 = triangle1.vertex(ind1_1);
const Point_2& vt2 = triangle1.vertex(ind1_2);
const Orientation or_s = orientation(vt1, vt2, triangle2.vertex(0));
for(int i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle2.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
else
{
const Point_2& vt1 = triangle2.vertex(ind2_1);
const Point_2& vt2 = triangle2.vertex(ind2_2);
const Orientation or_s = orientation(vt1, vt2, triangle1.vertex(0));
for(int i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle1.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle1,
const Triangle_2<K>& triangle2)
{
return K().compute_squared_distance_2_object()(triangle1, triangle2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H

View File

@ -19,6 +19,7 @@
#define CGAL_SQUARED_DISTANCE_UTILS_H
#include <CGAL/determinant.h>
#include <CGAL/number_utils.h>
#include <CGAL/wmult.h>
namespace CGAL {
@ -294,7 +295,6 @@ same_direction(const typename K::Vector_2 &u,
return same_direction_tag(u,v, k, tag);
}
} // namespace internal
} //namespace CGAL

View File

@ -14,11 +14,27 @@
//
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_2_H
#define CGAL_SQUARED_DISTANCE_2_H
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/squared_distance_2_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Segment_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Distance_2/Segment_2_Segment_2.h>
#include <CGAL/Distance_2/Segment_2_Ray_2.h>
#include <CGAL/Distance_2/Segment_2_Line_2.h>
#include <CGAL/Distance_2/Segment_2_Triangle_2.h>
#include <CGAL/Distance_2/Ray_2_Ray_2.h>
#include <CGAL/Distance_2/Ray_2_Line_2.h>
#include <CGAL/Distance_2/Ray_2_Triangle_2.h>
#include <CGAL/Distance_2/Line_2_Line_2.h>
#include <CGAL/Distance_2/Line_2_Triangle_2.h>
#include <CGAL/Distance_2/Triangle_2_Triangle_2.h>
#endif

View File

@ -1,857 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_SQUARED_DISTANCE_2_1_H
#define CGAL_SQUARED_DISTANCE_2_1_H
#include <CGAL/user_classes.h>
#include <CGAL/kernel_assertions.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/squared_distance_utils.h>
#include <CGAL/Kernel/global_functions_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_2 & pt1,
const typename K::Point_2 & pt2,
const K& k)
{
typename K::Vector_2 vec = k.construct_vector_2_object()(pt2, pt1);
return (typename K::FT)k.compute_squared_length_2_object()(vec);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K&,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
const RT & a = line.a();
const RT & b = line.b();
const RT & w = pt.hw();
RT n = a*pt.hx() + b*pt.hy() + w * line.c();
RT d = (CGAL_NTS square(a) + CGAL_NTS square(b)) * CGAL_NTS square(w);
return Rational_traits<FT>().make_rational(CGAL_NTS square(n), d);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K&,
const Cartesian_tag&)
{
typedef typename K::FT FT;
const FT & a = line.a();
const FT & b = line.b();
FT n = a*pt.x() + b*pt.y() + line.c();
FT d = CGAL_NTS square(a) + CGAL_NTS square(b);
return CGAL_NTS square(n)/d;
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K& k)
{
typedef typename K::Kernel_tag Tag;
Tag tag;
return squared_distance(pt, line, k, tag);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, line, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector;
Vector_2 diff = construct_vector(ray.source(), pt);
const Vector_2 &dir = ray.direction().vector();
if (!is_acute_angle(dir,diff, k) )
return (typename K::FT)k.compute_squared_length_2_object()(diff);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, ray, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::Vector_2 Vector_2;
typedef typename K::RT RT;
// assert that the segment is valid (non zero length).
Vector_2 diff = construct_vector(seg.source(), pt);
Vector_2 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k);
if (d <= (RT)0)
return (typename K::FT)k.compute_squared_length_2_object()(diff);
RT e = wdot(segvec,segvec, k);
if (wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return internal::squared_distance(pt, seg.target(), k);
return internal::squared_distance(pt, seg.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, seg, k);
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
const Vector_2 &dir1 = seg1.direction().vector();
const Vector_2 &dir2 = seg2.direction().vector();
if (same_direction(dir1, dir2, k)) {
if (!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return internal::squared_distance(seg1.target(), seg2.source(), k);
if (!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return internal::squared_distance(seg1.source(), seg2.target(), k);
} else {
if (!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return internal::squared_distance(seg1.target(), seg2.target(), k);
if (!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return internal::squared_distance(seg1.source(), seg2.source(), k);
}
return internal::squared_distance(seg2.source(), seg1.supporting_line(), k);
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT &startwcross,
const typename K::RT &endwcross,
const typename K::Point_2 &start,
const typename K::Point_2 &end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k,
const Cartesian_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
bool crossing1, crossing2;
RT c1s, c1e, c2s, c2e;
if (seg1.source() == seg1.target())
return internal::squared_distance(seg1.source(), seg2, k);
if (seg2.source() == seg2.target())
return internal::squared_distance(seg2.source(), seg1, k);
Orientation o1s = orientation(seg2.source(), seg2.target(), seg1.source());
Orientation o1e = orientation(seg2.source(), seg2.target(), seg1.target());
if (o1s == RIGHT_TURN) {
crossing1 = (o1e != RIGHT_TURN);
} else {
if (o1e != LEFT_TURN) {
if (o1s == COLLINEAR && o1e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
} else {
crossing1 = (o1s == COLLINEAR);
}
}
Orientation o2s = orientation(seg1.source(), seg1.target(), seg2.source());
Orientation o2e = orientation(seg1.source(), seg1.target(), seg2.target());
if (o2s == RIGHT_TURN) {
crossing2 = (o2e != RIGHT_TURN);
} else {
if (o2e != LEFT_TURN) {
if (o2s == COLLINEAR && o2e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
} else {
crossing2 = (o2s == COLLINEAR);
}
}
if (crossing1) {
if (crossing2)
return (FT)0;
c2s = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
c2e = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
Comparison_result dm = CGAL::compare(c2s,c2e);
if (dm == SMALLER) {
return internal::squared_distance(seg2.source(), seg1, k);
} else {
if (dm == LARGER) {
return internal::squared_distance(seg2.target(), seg1, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
c1s = CGAL::abs(wcross(seg2.source(), seg2.target(), seg1.source(), k));
c1e = CGAL::abs(wcross(seg2.source(), seg2.target(), seg1.target(), k));
Comparison_result dm = CGAL::compare(c1s,c1e);
if (crossing2) {
if (dm == SMALLER) {
return internal::squared_distance(seg1.source(), seg2, k);
} else {
if (dm == LARGER) {
return internal::squared_distance(seg1.target(), seg2, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
FT min1, min2;
if (dm == EQUAL)
return internal::squared_distance_parallel(seg1, seg2, k);
min1 = (dm == SMALLER) ?
internal::squared_distance(seg1.source(), seg2, k):
internal::squared_distance(seg1.target(), seg2, k);
c2s = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
c2e = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
dm = CGAL::compare(c2s,c2e);
if (dm == EQUAL) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
min2 = (dm == SMALLER) ?
internal::squared_distance(seg2.source(), seg1, k):
internal::squared_distance(seg2.target(), seg1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
bool crossing1, crossing2;
RT c1s, c1e, c2s, c2e;
if (seg1.source() == seg1.target())
return internal::squared_distance(seg1.source(), seg2, k);
if (seg2.source() == seg2.target())
return internal::squared_distance(seg2.source(), seg1, k);
c1s = wcross(seg2.source(), seg2.target(), seg1.source(), k);
c1e = wcross(seg2.source(), seg2.target(), seg1.target(), k);
c2s = wcross(seg1.source(), seg1.target(), seg2.source(), k);
c2e = wcross(seg1.source(), seg1.target(), seg2.target(), k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
if (c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
if (c2s < RT(0)) {
crossing2 = (c2e >= RT(0));
} else {
if (c2e <= RT(0)) {
if (c2s == RT(0) && c2e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
} else {
crossing2 = (c2s == RT(0));
}
}
if (crossing1) {
if (crossing2)
return (FT)0;
RT dm;
dm = _distance_measure_sub<K>(c2s,c2e, seg2.source(), seg2.target());
if (dm < RT(0)) {
return internal::squared_distance(seg2.source(), seg1, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg2.target(), seg1, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
if (crossing2) {
RT dm;
dm =
_distance_measure_sub<K>(c1s, c1e,seg1.source(),seg1.target());
if (dm < RT(0)) {
return internal::squared_distance(seg1.source(), seg2, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg1.target(), seg2, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
FT min1, min2;
RT dm = _distance_measure_sub<K>(
c1s, c1e, seg1.source(), seg1.target());
if (dm == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
min1 = (dm < RT(0)) ?
internal::squared_distance(seg1.source(), seg2, k):
internal::squared_distance(seg1.target(), seg2, k);
dm = _distance_measure_sub<K>(
c2s, c2e, seg2.source(), seg2.target());
if (dm == RT(0)) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
min2 = (dm < RT(0)) ?
internal::squared_distance(seg2.source(), seg1, k):
internal::squared_distance(seg2.target(), seg1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT &startwcross,
const typename K::RT &endwcross,
const typename K::Vector_2 &start,
const typename K::Vector_2 &end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2 &seg,
const typename K::Ray_2 &ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
const Vector_2 &dir1 = seg.direction().vector();
const Vector_2 &dir2 = ray.direction().vector();
if (same_direction(dir1, dir2, k)) {
if (!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return internal::squared_distance(seg.target(), ray.source(), k);
} else {
if (!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return internal::squared_distance(seg.source(), ray.source(), k);
}
return internal::squared_distance(ray.source(), seg.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
const Vector_2 &raydir = ray.direction().vector();
Vector_2 startvec(construct_vector(ray.source(), seg.source()));
Vector_2 endvec(construct_vector(ray.source(), seg.target()));
typename K::Orientation_2 orientation;
bool crossing1, crossing2;
RT c1s, c1e;
if (seg.source() == seg.target())
return internal::squared_distance(seg.source(), ray, k);
c1s = wcross(raydir, startvec, k);
c1e = wcross(raydir, endvec, k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
if (c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
switch (orientation(seg.source(), seg.target(), ray.source())) {
case LEFT_TURN:
crossing2 = right_turn(construct_vector(seg.source(), seg.target()), raydir, k);
break;
case RIGHT_TURN:
crossing2 = left_turn(construct_vector(seg.source(), seg.target()), raydir, k);
break;
default:
crossing2 = true;
break;
}
if (crossing1) {
if (crossing2)
return FT(0);
return internal::squared_distance(ray.source(), seg, k);
} else {
if (crossing2) {
RT dm;
dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm < RT(0)) {
return internal::squared_distance(seg.source(), ray, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg.target(), ray, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg, ray, k);
}
}
} else {
FT min1, min2;
RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
min1 = (dm < RT(0))
? internal::squared_distance(seg.source(), ray, k)
: internal::squared_distance(seg.target(), ray, k);
min2 = internal::squared_distance(ray.source(), seg, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Segment_2 &seg,
const K& k)
{
return internal::squared_distance(seg, ray, k);
}
template <class K>
typename K::FT
_sqd_to_line(const typename K::Vector_2 &diff,
const typename K::RT & wcross,
const typename K::Vector_2 &dir )
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT numerator = CGAL_NTS square(wcross);
RT denominator = wmult((K*)0, RT(wdot(dir,dir, K())),
diff.hw(), diff.hw());
return Rational_traits<FT>().make_rational(numerator, denominator);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Line_2 &line,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typedef typename K::Point_2 Point_2;
const Vector_2 &linedir = line.direction().vector();
const Point_2 &linepoint = line.point();
Vector_2 startvec(construct_vector(linepoint, seg.source()));
Vector_2 endvec(construct_vector(linepoint, seg.target()));
bool crossing1;
RT c1s, c1e;
if (seg.source() == seg.target())
return internal::squared_distance(seg.source(), line, k);
c1s = wcross(linedir, startvec, k);
c1e = wcross(linedir, endvec, k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
if (crossing1) {
return (FT)0;
} else {
RT dm;
dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm <= RT(0)) {
return _sqd_to_line<K>(startvec, c1s, linedir);
} else {
return _sqd_to_line<K>(endvec, c1e, linedir);
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Segment_2 &seg,
const K& k)
{
return internal::squared_distance(seg, line, k);
}
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(
const typename K::Vector_2 &ray1dir,
const typename K::Vector_2 &ray2dir,
const typename K::Vector_2 &from1to2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
if (!is_acute_angle(ray1dir, from1to2, k)) {
if (!same_direction(ray1dir, ray2dir, k))
return (typename K::FT)k.compute_squared_length_2_object()(from1to2);
}
RT wcr, w;
wcr = wcross(ray1dir, from1to2, k);
w = from1to2.hw();
return (typename K::FT)(FT(wcr*wcr)
/ FT(wmult((K*)0, RT(wdot(ray1dir, ray1dir, k)), w, w)));
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2 &ray1,
const typename K::Ray_2 &ray2,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::Vector_2 Vector_2;
typedef typename K::FT FT;
const Vector_2 &ray1dir = ray1.direction().vector();
const Vector_2 &ray2dir = ray2.direction().vector();
Vector_2 diffvec(construct_vector(ray1.source(),ray2.source()));
bool crossing1, crossing2;
switch (orientation(ray1dir, ray2dir, k)) {
case COUNTERCLOCKWISE:
crossing1 = !clockwise(diffvec, ray2dir, k);
crossing2 = !counterclockwise(ray1dir, diffvec, k);
break;
case CLOCKWISE:
crossing1 = !counterclockwise(diffvec, ray2dir, k);
crossing2 = !clockwise(ray1dir, diffvec, k);
break;
default:
return ray_ray_squared_distance_parallel(ray1dir,ray2dir,diffvec,k);
}
if (crossing1) {
if (crossing2)
return (FT)0;
return internal::squared_distance(ray2.source(), ray1, k);
} else {
if (crossing2) {
return internal::squared_distance(ray1.source(), ray2, k);
} else {
FT min1, min2;
min1 = internal::squared_distance(ray1.source(), ray2, k);
min2 = internal::squared_distance(ray2.source(), ray1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
Vector_2 normalvec(line.a(), line.b());
Vector_2 diff = construct_vector(line.point(), ray.source());
FT sign_dist = k.compute_scalar_product_2_object()(diff,normalvec);
if (sign_dist < FT(0)) {
if (is_acute_angle(normalvec, ray.direction().vector(), k) )
return (FT)0;
} else {
if (is_obtuse_angle(normalvec, ray.direction().vector(), k) )
return (FT)0;
}
return (typename K::FT)((sign_dist*sign_dist)/k.compute_squared_length_2_object()(normalvec));
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Line_2 &line,
const K& k)
{
return internal::squared_distance(line, ray, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line1,
const typename K::Line_2 &line2,
const K& k)
{
typedef typename K::FT FT;
if (internal::parallel(line1, line2, k))
return internal::squared_distance(line1.point(), line2, k);
else
return (FT)0;
}
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
if (!is_acute_angle(ray.direction().vector(), construct_vector(ray.source(), pt), k)) {
ind = 0;
return;
}
ind = -1;
}
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
if (!is_acute_angle(seg.target(),seg.source(),pt, k)) {
ind = 0;
return;
}
if (!is_acute_angle(seg.source(),seg.target(),pt, k)) {
ind = 1;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
int ind,
const K& k)
{
if (ind == 0)
return internal::squared_distance(pt, ray.source(), k);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
int ind,
const K& k)
{
if (ind == 0)
return internal::squared_distance(pt, seg.source(), k);
if (ind == 1)
return internal::squared_distance(pt, seg.target(), k);
return internal::squared_distance(pt, seg.supporting_line(), k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> & pt1, const Point_2<K> & pt2)
{
return internal::squared_distance(pt1, pt2, K());
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Line_2<K> &line)
{
return internal::squared_distance(pt, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> & line, const Point_2<K> & pt)
{
return squared_distance(pt, line);
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Ray_2<K> &ray)
{
return internal::squared_distance(pt, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Point_2<K> & pt)
{
return squared_distance(pt, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Segment_2<K> &seg)
{
return internal::squared_distance(pt, seg, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> & seg, const Point_2<K> & pt)
{
return internal::squared_distance(pt, seg, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg1, const Segment_2<K> &seg2)
{
typedef typename K::Kernel_tag Tag;
return internal::squared_distance(seg1, seg2, K(), Tag());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg, const Ray_2<K> &ray)
{
return internal::squared_distance(seg, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Segment_2<K> & seg)
{
return internal::squared_distance(seg, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg, const Line_2<K> &line)
{
return internal::squared_distance(seg, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> & line, const Segment_2<K> & seg)
{
return internal::squared_distance(seg, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray1, const Ray_2<K> &ray2)
{
return internal::squared_distance(ray1, ray2, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line, const Ray_2<K> &ray)
{
return internal::squared_distance(line, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Line_2<K> & line)
{
return internal::squared_distance(line, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line1, const Line_2<K> &line2)
{
return internal::squared_distance(line1, line2, K());
}
} //namespace CGAL
#endif

View File

@ -1,566 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_2_2_H
#define CGAL_SQUARED_DISTANCE_2_2_H
#include <CGAL/user_classes.h>
#include <CGAL/kernel_assertions.h>
#include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Line_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Triangle_2.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/squared_distance_utils.h>
#include <CGAL/squared_distance_2_1.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind1,
int &ind2,
const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k )
{
typename K::Left_turn_2 leftturn = k.left_turn_2_object();
typedef typename K::Point_2 Point_2;
const Point_2 &vt0 = triangle.vertex(0);
const Point_2 &vt1 = triangle.vertex(1);
const Point_2 &vt2 = triangle.vertex(2);
if (leftturn(vt0, vt1, vt2)) {
if (leftturn(pt, vt1, vt0)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
if (leftturn(pt, vt2, vt1)) {
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
}
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 1;
return;
} else {
if (leftturn(pt, vt2, vt1)) {
if (!is_acute_angle(vt1, vt2, pt, k)) {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
} else {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
} else {
if (leftturn(pt, vt2, vt0)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
if (leftturn(pt, vt1, vt2)) {
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
}
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 2;
return;
} else {
if (leftturn(pt, vt1, vt2)) {
if (!is_acute_angle(vt2, vt1, pt, k)) {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
} else {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
}
}
template <class K>
typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
int ind1, int ind2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Line_2 Line_2;
if (ind1 == -1)
return FT(0);
if (ind2 == -1)
return internal::squared_distance(pt, triangle.vertex(ind1), k);
return internal::squared_distance(pt,
Line_2(triangle.vertex(ind1), triangle.vertex(ind2)),
k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k)
{
int ind1,ind2;
distance_index<K>(ind1, ind2, pt, triangle, k);
return squared_distance_indexed(pt, triangle, ind1, ind2, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Point_2 & pt,
const K& k)
{
return internal::squared_distance(pt, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
Oriented_side side0;
side0 = line.oriented_side(triangle.vertex(0));
if (line.oriented_side(triangle.vertex(1)) != side0)
return FT(0);
if (line.oriented_side(triangle.vertex(2)) != side0)
return FT(0);
FT mindist, dist;
int i;
mindist = internal::squared_distance(triangle.vertex(0),line,k);
for (i=1; i<3; i++) {
dist = internal::squared_distance(triangle.vertex(i),line,k);
if (dist < mindist)
mindist = dist;
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Line_2 & line,
const K& k)
{
return internal::squared_distance(line, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typedef typename K::Line_2 Line_2;
int i, ind_tr1, ind_tr2, ind_ray = 0, ind1;
FT mindist, dist;
distance_index<K>(ind_tr1, ind_tr2, ray.source(), triangle, k);
mindist =
squared_distance_indexed(ray.source(), triangle, ind_tr1, ind_tr2, k);
for (i=0; i<3; i++) {
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, ray, k);
dist = squared_distance_indexed(pt, ray, ind1, k);
if (dist < mindist) {
ind_ray = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if (ind_tr2 == -1 && ind_ray != -1)
return mindist;
if (ind_tr2 != -1) {
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
if (clockwise(ray.direction().vector(), vt2-vt1, k)) {
mindist = FT(0);
}
} else {
// Check if all the triangle vertices lie
// at the same side of the segment.
const Line_2 &sl = ray.supporting_line();
Oriented_side or_s = sl.oriented_side(triangle.vertex(0));
for (i=1; i<3; i++) {
if (sl.oriented_side(triangle.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Ray_2 & ray,
const K& k)
{
return internal::squared_distance(ray, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation;
int i, ind_tr1 = 0, ind_tr2 = -1, ind_seg = 0, ind1, ind2;
FT mindist, dist;
mindist = internal::squared_distance(seg.source(), triangle.vertex(0), k);
for (i=0; i<2; i++) {
const Point_2 &pt = seg.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle, k);
dist = internal::squared_distance_indexed(pt, triangle, ind1, ind2, k);
if (dist < mindist) {
ind_seg = i;
ind_tr1 = ind1; ind_tr2 = ind2;
mindist = dist;
}
}
for (i=0; i<3; i++) {
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, seg, k);
dist = internal::squared_distance_indexed(pt, seg, ind1, k);
if (dist < mindist) {
ind_seg = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if (ind_tr2 == -1 && ind_seg != -1)
return mindist;
if (ind_tr2 != -1) {
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
Orientation or_s = orientation(vt1, vt2, seg.source());
if (orientation(vt1, vt2, seg.target()) != or_s) {
mindist = FT(0);
}
} else {
// Check if all the triangle vertices lie
// at the same side of the segment.
const Point_2 &vt1 = seg.source();
const Point_2 &vt2 = seg.target();
Orientation or_s = orientation(vt1, vt2, triangle.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Segment_2 & seg,
const K& k)
{
return internal::squared_distance(seg, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Triangle_2 &triangle1,
const typename K::Triangle_2 &triangle2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation;
int i, ind1_1 = 0,ind1_2 = -1, ind2_1 = 0, ind2_2 = -1, ind1, ind2;
FT mindist, dist;
mindist =
internal::squared_distance(triangle1.vertex(0), triangle2.vertex(0), k);
for (i=0; i<3; i++) {
const Point_2& pt = triangle1.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle2, k);
dist = squared_distance_indexed(pt, triangle2, ind1, ind2, k);
if (dist < mindist) {
ind1_1 = i; ind1_2 = -1;
ind2_1 = ind1; ind2_2 = ind2;
mindist = dist;
}
}
for (i=0; i<3; i++) {
const Point_2& pt = triangle2.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle1, k);
dist = squared_distance_indexed(pt, triangle1, ind1, ind2, k);
if (dist < mindist) {
ind1_1 = ind1; ind1_2 = ind2;
ind2_1 = i; ind2_2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the
// separating line.
if (ind1_2 == -1 && ind2_2 == -1)
return mindist;
// In case of point-segment closest distance, there is still the
// possibility of overlapping triangles. Check if all the
// vertices lie at the same side of the segment.
if (ind1_2 != -1) {
const Point_2 &vt1 = triangle1.vertex(ind1_1);
const Point_2 &vt2 = triangle1.vertex(ind1_2);
Orientation or_s = orientation(vt1, vt2, triangle2.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle2.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
} else {
const Point_2 &vt1 = triangle2.vertex(ind2_1);
const Point_2 &vt2 = triangle2.vertex(ind2_2);
Orientation or_s = orientation(vt1, vt2, triangle1.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle1.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(pt, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Point_2<K> &pt)
{
return internal::squared_distance(pt, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(line, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Line_2<K> &line)
{
return internal::squared_distance(line, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(ray, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Ray_2<K> &ray)
{
return internal::squared_distance(ray, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(seg, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Segment_2<K> &seg)
{
return internal::squared_distance(seg, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle1,
const Triangle_2<K> &triangle2)
{
return internal::squared_distance(triangle1, triangle2, K());
}
} //namespace CGAL
#endif

View File

@ -1,12 +1,12 @@
// 2D distance tests.
#ifdef NDEBUG
#undef NDEBUG //this testsuite requires NDEBUG to be not defined
#endif
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Simple_homogeneous.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Homogeneous.h>
#include <vector>
#include <iostream>
@ -167,7 +167,7 @@ struct Test {
check_squared_distance (R(p( 4, 0), p(-3, -1)), R(p( 1, 1), p( 2, 11)), 2);
}
void R_S()
void S_R()
{
std::cout << "Ray - Segment\n";
check_squared_distance (R(p(2, 0), p( 0, 2)), S(p( 1, 1), p( 4, 0)), 0);
@ -216,7 +216,7 @@ struct Test {
check_squared_distance (p( 1, 1), L(p( 4, 0), p( -3, -1)), 2);
}
void L_S()
void S_L()
{
std::cout << "Line - Segment\n";
check_squared_distance (L(p( 0, 0), p( 1, 0)), S(p( 2, 2), p( 3, 3)), 4);
@ -268,29 +268,38 @@ struct Test {
void run()
{
std::cout << "2D Distance tests\n";
std::cout << "-- Kernel: " << typeid(K).name() << std::endl;
P_P();
P_S();
S_S();
P_R();
R_R();
R_S();
R_L();
P_L();
L_S();
L_L();
P_T();
L_T();
R_T();
S_S();
S_T();
S_R();
S_L();
R_R();
R_L();
R_T();
L_L();
L_T();
T_T();
}
};
int main()
{
Test< CGAL::Simple_cartesian<double> >().run();
Test< CGAL::Simple_homogeneous<double> >().run();
// TODO : test more kernels.
std::cout << "2D Distance tests\n";
Test<CGAL::Simple_cartesian<double> >().run();
Test<CGAL::Simple_homogeneous<double> >().run();
Test<CGAL::Homogeneous<CGAL::Epeck_ft> >().run();
Test<CGAL::Exact_predicates_inexact_constructions_kernel>().run();
Test<CGAL::Exact_predicates_exact_constructions_kernel>().run();
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_LINE_3_LINE_3_H
#define CGAL_DISTANCE_3_LINE_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line1,
const typename K::Line_3& line2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir1 = line1.direction().vector();
const Vector_3 dir2 = line2.direction().vector();
const Vector_3 normal = wcross(dir1, dir2, k);
const Vector_3 diff = vector(line1.point(), line2.point());
if (is_null(normal, k))
return squared_distance_to_line(dir2, diff, k);
return squared_distance_to_plane(normal, diff, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line1,
const Line_3<K>& line2)
{
return K().compute_squared_distance_3_object()(line1, line2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_LINE_3_LINE_3_H

View File

@ -0,0 +1,86 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_LINE_3_PLANE_3_H
#define CGAL_DISTANCE_3_LINE_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
bool
contains_vector(const typename K::Plane_3& pl,
const typename K::Vector_3& vec,
const K&)
{
typedef typename K::RT RT;
return pl.a()*vec.hx() + pl.b()*vec.hy() + pl.c() * vec.hz() == RT(0);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& l,
const typename K::Plane_3& pl,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
if(contains_vector(pl, l.direction().vector(), k))
return sq_dist(pl, l.point());
return FT(0);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& pl,
const typename K::Line_3& l,
const K& k)
{
return squared_distance(l, pl, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(line, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(plane, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_LINE_3_PLANE_3_H

View File

@ -0,0 +1,55 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_PLANE_3_PLANE_3_H
#define CGAL_DISTANCE_3_PLANE_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane1,
const typename K::Plane_3& plane2,
const K& k)
{
typename K::Construct_orthogonal_vector_3 ortho_vec = k.construct_orthogonal_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
if(!is_null(wcross(ortho_vec(plane1), ortho_vec(plane2), k), k))
return typename K::FT(0);
else
return sq_dist(plane1.point(), plane2);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane1,
const Plane_3<K>& plane2)
{
return K().compute_squared_distance_3_object()(plane1, plane2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_PLANE_3_PLANE_3_H

View File

@ -0,0 +1,91 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri, Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_POINT_3_LINE_3_H
#define CGAL_DISTANCE_3_POINT_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Point_3.h>
namespace CGAL {
namespace internal {
template <class K>
void
squared_distance_RT(const typename K::Point_3 &pt,
const typename K::Line_3 &line,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3& dir = line.direction().vector();
const Vector_3 diff = vector(line.point(), pt);
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>
inline
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(pt, line);
}
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(line, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_LINE_3_H

View File

@ -0,0 +1,73 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_PLANE_3_H
#define CGAL_DISTANCE_3_POINT_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Plane_3& plane,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
Vector_3 diff = vector(plane.point(), pt);
return squared_distance_to_plane(plane.orthogonal_vector(), diff, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(pt, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(plane, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_PLANE_3_H

View File

@ -0,0 +1,48 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_POINT_3_H
#define CGAL_DISTANCE_3_POINT_3_POINT_3_H
#include <CGAL/Point_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3& pt1,
const typename K::Point_3& pt2,
const K& k)
{
return k.compute_squared_distance_3_object()(pt1, pt2);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt1,
const Point_3<K>& pt2)
{
return internal::squared_distance(pt1, pt2, K());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_POINT_3_H

View File

@ -0,0 +1,112 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri, Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_POINT_3_RAY_3_H
#define CGAL_DISTANCE_3_POINT_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
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)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir = ray.direction().vector();
const Vector_3 diff = vector(ray.source(), pt);
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>
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Ray_3& ray,
const K& k)
{
// 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;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir = ray.direction().vector();
const Vector_3 diff = vector(ray.source(), pt);
if(!is_acute_angle(dir, diff, k))
return diff*diff;
return squared_distance_to_line(dir, diff, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, ray, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(pt, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(ray, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_RAY_3_H

View File

@ -0,0 +1,133 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H
#define CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Segment_3.h>
namespace CGAL {
namespace internal {
template <class K>
void
squared_distance_RT(const typename K::Point_3& pt,
const typename K::Segment_3& seg,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
// assert that the segment is valid (non zero length).
const Vector_3 diff_s = vector(seg.source(), pt);
const Vector_3 segvec = 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 = 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>
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Segment_3& seg,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
// assert that the segment is valid (non zero length).
const Vector_3 diff = vector(seg.source(), pt);
const Vector_3 segvec = vector(seg.source(), seg.target());
const RT d = wdot(diff, segvec, k);
if(d <= RT(0))
return (FT(diff*diff));
const 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'
const Vector_3 wcr = wcross(segvec, diff, k);
return FT(wcr*wcr) / wmult((K*)0, e, diff.hw(), diff.hw());
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, seg, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(pt, seg);
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(seg, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H

View File

@ -0,0 +1,148 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H
#define CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Tetrahedron_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Tetrahedron_3& tet,
const K& k)
{
typedef typename K::Point_3 Point_3;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
typename K::Orientation_3 orientation = k.orientation_3_object();
bool on_bounded_side = true;
const Point_3& t0 = vertex(tet, 0);
const Point_3& t1 = vertex(tet, 1);
const Point_3& t2 = vertex(tet, 2);
const Point_3& t3 = vertex(tet, 3);
bool dmin_initialized = false;
typename K::FT dmin;
bool inside = false;
if(orientation(t0,t1,t2, pt) == NEGATIVE)
{
on_bounded_side = false;
dmin = squared_distance_to_triangle(pt, t0, t1, t2, k, inside);
dmin_initialized = true;
if(inside)
return dmin;
}
if(orientation(t0,t3,t1, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t0, t3, t1, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(orientation(t1,t3,t2, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t1, t3, t2, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(orientation(t2,t3,t0, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t2, t3, t0, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(on_bounded_side)
return typename K::FT(0);
return dmin;
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Tetrahedron_3& tet,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, tet, k);
}
} // namespace internal
template <class K>
typename K::FT
squared_distance(const Tetrahedron_3<K>& tet,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(tet, pt);
}
template <class K>
typename K::FT
squared_distance(const Point_3<K>& pt,
const Tetrahedron_3<K>& tet)
{
return K().compute_squared_distance_3_object()(pt, tet);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H

View File

@ -0,0 +1,242 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H
#define CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Distance_3/Point_3_Segment_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Triangle_3.h>
namespace CGAL {
namespace internal {
// returns true iff pt is on the negative side of the plane defined by (ep0, ep1) and normal
template <class K>
inline bool
on_left_of_triangle_edge(const typename K::Point_3& pt,
const typename K::Vector_3& normal,
const typename K::Point_3& ep0,
const typename K::Point_3& ep1,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 edge = vector(ep0, ep1);
const Vector_3 diff = vector(ep0, pt);
return (wdot(wcross(edge, normal, k), diff, k) <= RT(0));
}
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)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
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, segment(t2, t0), num, den, k);
typename K::RT num2, den2;
squared_distance_RT(pt, segment(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,
// but leaving it for robustness
squared_distance_RT(pt, segment(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, segment(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, segment(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, segment(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>
inline typename K::FT
squared_distance_to_triangle(const typename K::Point_3& pt,
const typename K::Point_3& t0,
const typename K::Point_3& t1,
const typename K::Point_3& t2,
const K& k,
bool& inside)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
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.
//
// Note that in the degenerate case, at most 2 edges cover the full triangle,
// and only two distances could be used, but leaving 3 for the case of
// inexact constructions as it might improve the accuracy.
typename K::FT d1 = sq_dist(pt, segment(t2, t0));
typename K::FT d2 = sq_dist(pt, segment(t1, t2));
typename K::FT d3 = sq_dist(pt, segment(t0, t1));
return (std::min)((std::min)(d1, d2), d3);
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01)
return sq_dist(pt, segment(t0, t1));
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12)
return sq_dist(pt, segment(t1, t2));
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20)
return sq_dist(pt, segment(t2, t0));
// The projection of pt is inside the triangle
inside = true;
return squared_distance_to_plane(normal, vector(t0, pt), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Triangle_3& t,
const K& k)
{
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
bool unused_inside = false;
return squared_distance_to_triangle(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
k,
unused_inside);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_3& t,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, t, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Triangle_3<K>& t)
{
return K().compute_squared_distance_3_object()(pt, t);
}
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K>& t,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(t, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H

View File

@ -0,0 +1,47 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H
#define CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Weighted_point_3.h>
namespace CGAL {
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K>& wpt,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(wpt.point(), pt);
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Weighted_point_3<K>& wpt)
{
return K().compute_squared_distance_3_object()(pt, wpt.point());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H

View File

@ -0,0 +1,102 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_LINE_3_H
#define CGAL_DISTANCE_3_RAY_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Line_3& line,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::Point_3 Point_3;
typedef typename K::RT RT;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Point_3& rs = ray.source();
const Vector_3 linedir = line.direction().vector();
const Vector_3 raydir = ray.direction().vector();
const Vector_3 normal = wcross(raydir, linedir, k);
const Vector_3 rs_min_lp = vector(line.point(), rs);
if(is_null(normal, k))
return squared_distance_to_line(linedir, rs_min_lp, k);
bool crossing;
const Vector_3 perpend2l = wcross(linedir, normal, k);
const RT sdm_sr_l = wdot(perpend2l, rs_min_lp, k);
if(sdm_sr_l < RT(0))
{
crossing = (wdot(perpend2l, raydir, k) >= RT(0));
}
else
{
if(wdot(perpend2l, raydir, k) <= RT(0))
crossing = true;
else
crossing = (sdm_sr_l == RT(0));
}
if(crossing)
return squared_distance_to_plane(normal, rs_min_lp, k);
else
return squared_distance_to_line(linedir, rs_min_lp, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Ray_3& ray,
const K& k)
{
return squared_distance(ray, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(line, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(ray, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_LINE_3_H

View File

@ -0,0 +1,97 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_PLANE_3_H
#define CGAL_DISTANCE_3_RAY_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/number_utils.h>
#include <CGAL/Plane_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3 &ray,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
const Point_3& start = ray.start();
const Point_3& planepoint = plane.point();
const Vector_3 start_min_pp = construct_vector(planepoint, start);
const Vector_3 end_min_pp = ray.direction().vector();
const Vector_3 normal = plane.orthogonal_vector();
const RT sdm_rs2pp = wdot(normal, start_min_pp, k);
const RT sdm_re2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_rs2pp))
{
case -1:
if(sdm_re2pp > RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if(sdm_re2pp < RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Ray_3& ray,
const K& k)
{
return squared_distance(ray, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(ray, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(plane, ray);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_PLANE_3_H

View File

@ -0,0 +1,143 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_RAY_3_H
#define CGAL_DISTANCE_3_RAY_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Ray_3.h>
#include <CGAL/Vector_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(const typename K::Vector_3& ray1dir,
const typename K::Vector_3& ray2dir,
const typename K::Vector_3& s1_min_s2,
const K& k)
{
if(!is_acute_angle(ray2dir, s1_min_s2, k))
if(!same_direction(ray1dir, ray2dir, k))
return typename K::FT(s1_min_s2*s1_min_s2);
return squared_distance_to_line(ray1dir, s1_min_s2, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray1,
const typename K::Ray_3& ray2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& s1 = ray1.source();
const Point_3& s2 = ray2.source();
const Vector_3 dir1 = ray1.direction().vector();
const Vector_3 dir2 = ray2.direction().vector();
const Vector_3 normal = wcross(dir1, dir2, k);
const Vector_3 s1_min_s2 = construct_vector(s2, s1);
if(is_null(normal, k))
return ray_ray_squared_distance_parallel(dir1, dir2, s1_min_s2, k);
bool crossing1, crossing2;
const Vector_3 perpend1 = wcross(dir1, normal, k);
const Vector_3 perpend2 = wcross(dir2, normal, k);
const RT sdm_s1_2 = wdot(perpend2, s1_min_s2, k);
if(sdm_s1_2 < RT(0))
{
crossing1 = (wdot(perpend2, dir1, k) >= RT(0));
}
else
{
if(RT(wdot(perpend2, dir1, k)) <= RT(0))
crossing1 = true;
else
crossing1 = (sdm_s1_2 == RT(0));
}
const RT sdm_s2_1 = - wdot(perpend1, s1_min_s2, k);
if(sdm_s2_1 < RT(0))
{
crossing2 = (wdot(perpend1, dir2, k) >= RT(0));
}
else
{
if(wdot(perpend1, dir2, k) <= RT(0))
crossing2 = true;
else
crossing2 = (sdm_s2_1 == RT(0));
}
if(crossing1)
{
if(crossing2)
return squared_distance_to_plane(normal, s1_min_s2, k);
return sq_dist(s2, ray1);
}
else
{
if(crossing2)
{
return sq_dist(s1, ray2);
}
else
{
FT min1, min2;
min1 = sq_dist(s1, ray2);
min2 = sq_dist(s2, ray1);
return (min1 < min2) ? min1 : min2;
}
}
}
} // namespace internal
template <class K>
inline
typename K::FT
ray_ray_squared_distance_parallel(const Vector_3<K>& ray1dir,
const Vector_3<K>& ray2dir,
const Vector_3<K>& s1_min_s2)
{
return internal::ray_ray_squared_distance_parallel(ray1dir, ray2dir, s1_min_s2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray1,
const Ray_3<K>& ray2)
{
return K().compute_squared_distance_3_object()(ray1, ray2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_RAY_3_H

View File

@ -0,0 +1,116 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Segment_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Line_3& line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& linepoint = line.point();
const Point_3& start = seg.source();
const Point_3& end = seg.target();
if(start == end)
return sq_dist(start, line);
const Vector_3 linedir = line.direction().vector();
const Vector_3 segdir = seg.direction().vector();
const Vector_3 normal = wcross(segdir, linedir, k);
if(is_null(normal, k))
return squared_distance_to_line(linedir, vector(linepoint,start), k);
bool crossing;
const Vector_3 perpend2line = wcross(linedir, normal, k);
const Vector_3 start_min_lp = vector(linepoint, start);
const Vector_3 end_min_lp = vector(linepoint, end);
const RT sdm_ss2l = wdot(perpend2line, start_min_lp, k);
const RT sdm_se2l = wdot(perpend2line, end_min_lp, k);
if(sdm_ss2l < RT(0)) {
crossing = (sdm_se2l >= RT(0));
} else {
if(sdm_se2l <= RT(0)) {
crossing = true;
} else {
crossing = (sdm_ss2l == RT(0));
}
}
if(crossing) {
return squared_distance_to_plane(normal, start_min_lp, k);
} else {
const RT dm = distance_measure_sub(sdm_ss2l, sdm_se2l, start_min_lp, end_min_lp, k);
if(dm <= RT(0)) {
return squared_distance_to_line(linedir, start_min_lp, k);
} else {
return squared_distance_to_line(linedir, end_min_lp, k);
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(seg, line);
}
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(line, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3 &seg,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_3 Vector_3;
typedef typename K::Point_3 Point_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Point_3& start = seg.start();
const Point_3& end = seg.end();
if (start == end)
return squared_distance(start, plane, k);
const Point_3& planepoint = plane.point();
const Vector_3 start_min_pp = vector(planepoint, start);
const Vector_3 end_min_pp = vector(planepoint, end);
const Vector_3& normal = plane.orthogonal_vector();
const RT sdm_ss2pp = wdot(normal, start_min_pp, k);
const RT sdm_se2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_ss2pp))
{
case -1:
if (sdm_se2pp >= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() >= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_se2pp <= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() <= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(seg, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(plane, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H

View File

@ -0,0 +1,200 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_3& seg,
const typename K::Ray_3& ray,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
const Vector_3 dir1 = seg.direction().vector();
const Vector_3 dir2 = ray.direction().vector();
bool same_direction;
if(CGAL_NTS abs(dir1.hx()) > CGAL_NTS abs(dir1.hy()))
same_direction = (CGAL_NTS sign(dir1.hx()) == CGAL_NTS sign(dir2.hx()));
else
same_direction = (CGAL_NTS sign(dir1.hy()) == CGAL_NTS sign(dir2.hy()));
if(same_direction)
{
if(!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return squared_distance(seg.target(), ray.source(), k);
}
else
{
if(!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return squared_distance(seg.source(), ray.source(), k);
}
return squared_distance(ray.source(), seg.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Ray_3& ray,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& ss = seg.source();
const Point_3& se = seg.target();
if(ss == se)
return sq_dist(ss, ray);
const Vector_3 raydir = ray.direction().vector();
const Vector_3 segdir = seg.direction().vector();
const Vector_3 normal = wcross(segdir, raydir, k);
if(is_null(normal, k))
return squared_distance_parallel(seg, ray, k);
bool crossing1, crossing2;
const Vector_3 perpend2seg = wcross(segdir, normal, k);
const Vector_3 perpend2ray = wcross(raydir, normal, k);
const Vector_3 ss_min_rs = vector(ray.source(), ss);
const Vector_3 se_min_rs = vector(ray.source(), se);
const RT sdm_ss2r = wdot(perpend2ray, ss_min_rs, k);
const RT sdm_se2r = wdot(perpend2ray, se_min_rs, k);
if(sdm_ss2r < RT(0))
{
crossing1 = (sdm_se2r >= RT(0));
}
else
{
if(sdm_se2r <= RT(0))
crossing1 = true;
else
crossing1 = (sdm_ss2r == RT(0));
}
const RT sdm_rs2s = - wdot(perpend2seg, ss_min_rs, k);
const RT sdm_re2s = wdot(perpend2seg, raydir, k);
if(sdm_rs2s < RT(0))
{
crossing2 = (sdm_re2s >= RT(0));
} else
{
if(sdm_re2s <= RT(0))
crossing2 = true;
else
crossing2 = (sdm_rs2s == RT(0));
}
if(crossing1)
{
if(crossing2)
return squared_distance_to_plane(normal, ss_min_rs, k);
return sq_dist(ray.source(), seg);
}
else
{
if(crossing2)
{
const RT dm = distance_measure_sub(sdm_ss2r, sdm_se2r, ss_min_rs, se_min_rs, k);
if(dm < RT(0))
{
return sq_dist(ss, ray);
}
else
{
if(dm > RT(0))
return sq_dist(se, ray);
else
// parallel, should not happen (no crossing)
return squared_distance_parallel(seg, ray, k);
}
}
else
{
const RT dm = distance_measure_sub(sdm_ss2r, sdm_se2r, ss_min_rs, se_min_rs, k);
if(dm == RT(0))
return squared_distance_parallel(seg, ray, k);
const FT min1 = (dm < RT(0)) ? sq_dist(ss, ray)
: sq_dist(se, ray);
const FT min2 = sq_dist(ray.source(), seg);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, ray, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance_parallel(const Segment_3<K>& seg,
const Ray_3<K>& ray)
{
return internal::squared_distance_parallel(ray, seg, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(seg, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(ray, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H

View File

@ -0,0 +1,208 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <boost/algorithm/clamp.hpp>
namespace CGAL {
namespace Distance_3 {
namespace internal {
template <typename K>
struct Segment_3_Segment_3_Result
{
typename K::FT x, y;
typename K::FT squared_distance;
};
// Using Lumelsky, 'On Fast Computation of Distance Between Line Segments' 1984
template <typename K>
Segment_3_Segment_3_Result<K>
squared_distance(const typename K::Segment_3& s1,
const typename K::Segment_3& s2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
typename K::Construct_vector_3 cv = k.construct_vector_3_object();
typename K::Compute_scalar_product_3 sp = k.compute_scalar_product_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
Segment_3_Segment_3_Result<K> res;
const Point_3& p1 = vertex(s1, 0);
const Point_3& q1 = vertex(s1, 1);
const Point_3& p2 = vertex(s2, 0);
const Point_3& q2 = vertex(s2, 1);
const Vector_3 v1 = cv(p1, q1), v2 = cv(p2, q2);
const Vector_3 p1p2 = cv(p1, p2);
// @todo compute these only when needed?
const FT a = sp(v1, v1);
const FT b = - sp(v1, v2);
const FT c = - b;
const FT d = - sp(v2, v2);
const FT e = sp(v1, p1p2);
const FT f = sp(v2, p1p2);
if(p1 == q1)
{
if(p2 == q2)
{
res.x = 0;
res.y = 0;
res.squared_distance = sq_dist(p1, p2);
return res;
}
CGAL_assertion(d < 0);
res.x = 0;
res.y = boost::algorithm::clamp<FT>(f/d, 0, 1); // (f - x*c) / d
res.squared_distance = sq_dist(p1, p2 + res.y*v2);
return res;
}
else if(p2 == q2)
{
CGAL_assertion(a > 0);
res.y = 0;
res.x = boost::algorithm::clamp<FT>(e/a, 0, 1); // (e + y*c) / a
res.squared_distance = sq_dist(p1 + res.x*v1, p2);
return res;
}
CGAL_assertion(a > 0 && d < 0);
const FT det = a*d - b*c;
if(det == 0)
res.x = 0;
else
res.x = boost::algorithm::clamp<FT>((e*d - b*f) / det, 0, 1);
FT xc = res.x*c;
// res.y = (f - xc) / d, by definition, but building it up more efficiently
if(f > xc) // y < 0 <=> f - xc / d < 0 <=> f - xc > 0 (since d is -||v2||)
{
res.y = 0;
res.x = boost::algorithm::clamp<FT>(e/a, 0, 1); // (e + y*c) / a
}
else // y >= 0
{
FT n = f - xc; // delay the division by d
if(n < d) // y > 1 <=> n / d > 1 <=> n < d (once again, important to note that d is negative!)
{
res.y = 1;
res.x = boost::algorithm::clamp<FT>((e + c) / a, 0, 1); // (e + y*c) / a
}
else // 0 <= y <= 1
{
res.y = n / d;
}
}
CGAL_postcondition(FT(0) <= res.x && res.x <= FT(1));
CGAL_postcondition(FT(0) <= res.y && res.y <= FT(1));
res.squared_distance = sq_dist(p1 + res.x*v1, p2 + res.y*v2);
CGAL_postcondition(res.squared_distance >= FT(0));
return res;
}
} // namespace internal
} // namespace Distance_3
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_3& seg1,
const typename K::Segment_3& seg2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Vector_3 dir1 = seg1.direction().vector();
const Vector_3 dir2 = seg2.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return sq_dist(seg1.target(), seg2.source(), k);
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return sq_dist(seg1.source(), seg2.target(), k);
}
else
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return sq_dist(seg1.target(), seg2.target(), k);
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return sq_dist(seg1.source(), seg2.source(), k);
}
return sq_dist(seg2.source(), seg1.supporting_line(), k);
}
template <typename K>
typename K::FT
squared_distance(const typename K::Segment_3& seg1,
const typename K::Segment_3& seg2,
const K& k)
{
Distance_3::internal::Segment_3_Segment_3_Result<K> res =
Distance_3::internal::squared_distance(seg1, seg2, k);
return res.squared_distance;
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance_parallel(const Segment_3<K>& seg1,
const Segment_3<K>& seg2)
{
return internal::squared_distance_parallel(seg1, seg2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg1,
const Segment_3<K>& seg2)
{
return K().compute_squared_distance_3_object()(seg1, seg2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H

View File

@ -0,0 +1,229 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H
#define CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/Segment_3_Segment_3.h>
#include <CGAL/Triangle_3.h>
namespace CGAL {
namespace Distance_3 {
namespace internal {
template <typename K>
std::pair<Segment_3_Segment_3_Result<K>, bool>
test_edge_pair(const typename K::Point_3& p1,
const typename K::Point_3& q1,
const typename K::Point_3& r1,
const typename K::Point_3& p2,
const typename K::Point_3& q2,
const typename K::Point_3& r2,
const K& k,
typename K::FT& global_min_sqd,
bool& are_triangles_known_to_be_disjoint)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Compute_scalar_product_3 scalar_product = k.compute_scalar_product_3_object();
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
typename K::Construct_scaled_vector_3 scale_vector = k.construct_scaled_vector_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_translated_point_3 translate = k.construct_translated_point_3_object();
Distance_3::internal::Segment_3_Segment_3_Result<K> res =
internal::squared_distance(segment(p1, q1), segment(p2, q2), k);
if(res.squared_distance <= global_min_sqd)
global_min_sqd = res.squared_distance;
else
return std::make_pair(res, false);
const Vector_3 v1 = vector(p1, q1), v2 = vector(p2, q2);
const Point_3 m1 = translate(p1, scale_vector(v1, res.x));
const Point_3 m2 = translate(p2, scale_vector(v2, res.y));
const Vector_3 vr1 = vector(m1, r1), vr2 = vector(m2, r2);
const Vector_3 n = vector(m1, m2);
const FT sp_r1 = scalar_product(vr1, n);
const FT sp_r2 = scalar_product(vr2, n);
const bool is_r1_closer = (sp_r1 > 0); // Plane_3{m1, n}.has_on_positive_side(r1);
const bool is_r2_closer = (sp_r2 < 0); // Plane_3{m2, -n}.has_on_positive_side(r2);
const bool is_best_pair = !is_r1_closer && !is_r2_closer;
// Even if it is not the best pair, one may be able to deduce if the triangles do not intersect
// by checking if there is a void space between the planes orthogonal to the vector realizing
// the min distance between the edges and passing through the third points.
if(!is_best_pair)
{
FT separating_distance = res.squared_distance;
if(is_r1_closer)
separating_distance -= sp_r1;
if(is_r2_closer)
separating_distance += sp_r2;
if(separating_distance > 0)
are_triangles_known_to_be_disjoint = true;
}
return std::make_pair(res, is_best_pair);
}
template <typename K>
std::pair<typename K::FT, bool>
test_vertex_triangle(const typename K::Triangle_3& tr1,
const typename K::Triangle_3& tr2,
const K& k,
bool& are_triangles_known_to_be_disjoint)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Compute_scalar_product_3 scalar_product = k.compute_scalar_product_3_object();
typename K::Construct_cross_product_vector_3 cross_product = k.construct_cross_product_vector_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
const Point_3& p1 = vertex(tr1, 0);
const Point_3& q1 = vertex(tr1, 1);
const Point_3& r1 = vertex(tr1, 2);
const Point_3& p2 = vertex(tr2, 0);
const Point_3& q2 = vertex(tr2, 1);
const Point_3& r2 = vertex(tr2, 2);
const Vector_3 p2q2 = vector(p2, q2);
const Vector_3 p2r2 = vector(p2, r2);
const Vector_3 n2 = cross_product(p2q2, p2r2);
if(scalar_product(n2, n2) == FT(0))
return std::make_pair(0, false);
std::array<FT, 3> sps = { scalar_product(vector(p2, p1), n2),
scalar_product(vector(p2, q1), n2),
scalar_product(vector(p2, r1), n2) };
// All the vertices of tr1 must be on the same side of tr2
// Coplanarity is tolerated, so '1' and '0' should be allowed, but not '1' and '-1'
if(CGAL::sign(sps[0]) == - CGAL::sign(sps[1]) || CGAL::sign(sps[1]) == - CGAL::sign(sps[2]))
return std::make_pair(0, false);
std::for_each(sps.begin(), sps.end(), [](FT& v) { v = abs(v); });
const auto min_pos = std::min_element(sps.begin(), sps.end());
const std::size_t min_id = static_cast<std::size_t>(std::distance(sps.begin(), min_pos));
if(sps[min_id] > 0)
are_triangles_known_to_be_disjoint = true;
const Point_3& x1 = vertex(tr1, static_cast<int>(min_id));
if(CGAL::internal::on_left_of_triangle_edge(x1, n2, p2, q2, k) &&
CGAL::internal::on_left_of_triangle_edge(x1, n2, q2, r2, k) &&
CGAL::internal::on_left_of_triangle_edge(x1, n2, r2, p2, k))
{
// the projection of `x1` is inside the triangle
return std::make_pair(CGAL::internal::squared_distance_to_plane(n2, vector(p2, x1), k), true);
}
return std::make_pair(0, false);
}
} // namespace internal
} // namespace Distance_3
namespace internal {
template <typename K>
typename K::FT
squared_distance(const typename K::Triangle_3& tr1,
const typename K::Triangle_3& tr2,
const K& k)
{
typedef typename K::FT FT;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
// ideally just limits<FT>::infinity|max(), but it is not available for exact NTs...
FT global_min_sqd = squared_distance(vertex(tr1, 0), vertex(tr2, 0));
bool are_triangles_known_to_be_disjoint = false;
std::pair<Distance_3::internal::Segment_3_Segment_3_Result<K>, bool> ss_res;
for(int i=0; i<3; ++i)
{
for(int j=0; j<3; ++j)
{
ss_res = Distance_3::internal::test_edge_pair(
vertex(tr1, i%3), vertex(tr1, (i+1)%3), vertex(tr1, (i+2)%3),
vertex(tr2, j%3), vertex(tr2, (j+1)%3), vertex(tr2, (j+2)%3), k,
global_min_sqd, are_triangles_known_to_be_disjoint);
if(ss_res.second)
return ss_res.first.squared_distance;
}
}
// Failed to find a minimum between segment pairs, explore vertex-triangle distances
#if 1
std::pair<FT, bool> pt_res =
Distance_3::internal::test_vertex_triangle(tr1, tr2, k, are_triangles_known_to_be_disjoint);
if(pt_res.second)
return pt_res.first;
pt_res = Distance_3::internal::test_vertex_triangle(tr2, tr1, k, are_triangles_known_to_be_disjoint);
if(pt_res.second)
return pt_res.first;
if(are_triangles_known_to_be_disjoint)
return global_min_sqd;
else
return 0;
#else // A tiny bit less efficient, but a lot clearer!
// @todo does not handle degenerate inputs
if(!are_triangles_known_to_be_disjoint && CGAL::do_intersect(tr1, tr2))
return 0;
FT sqd_p1 = CGAL::squared_distance(vertex(tr1, 0), tr2);
FT sqd_q1 = CGAL::squared_distance(vertex(tr1, 1), tr2);
FT sqd_r1 = CGAL::squared_distance(vertex(tr1, 2), tr2);
FT sqd_p2 = CGAL::squared_distance(vertex(tr2, 0), tr1);
FT sqd_q2 = CGAL::squared_distance(vertex(tr2, 1), tr1);
FT sqd_r2 = CGAL::squared_distance(vertex(tr2, 2), tr1);
const FT m = std::min({sqd_p1, sqd_q1, sqd_r1, sqd_p2, sqd_q2, sqd_r2});
return m;
#endif
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K>& tr1,
const Triangle_3<K>& tr2)
{
return K().compute_squared_distance_3_object()(tr1, tr2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H

View File

@ -0,0 +1,35 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H
#define CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H
#include <CGAL/Weighted_point_3.h>
namespace CGAL {
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K>& wpt1,
const Weighted_point_3<K>& wpt2)
{
return K().compute_squared_distance_3_object()(wpt1.point(), wpt2.point());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H

View File

@ -12,36 +12,27 @@
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_UTILS_3_H
#define CGAL_SQUARED_DISTANCE_UTILS_3_H
#ifndef CGAL_DISTANCE_3_0_H
#define CGAL_DISTANCE_3_0_H
#include <CGAL/kernel_assertions.h>
#include <CGAL/determinant.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/Point_3.h>
#include <CGAL/Weighted_point_3.h>
#include <CGAL/Vector_3.h>
#include <CGAL/number_utils.h>
#include <CGAL/Rational_traits.h>
#include <CGAL/wmult.h>
namespace CGAL {
namespace internal {
template <class K>
bool is_null(const typename K::Vector_3 &v, const K&)
{
typedef typename K::RT RT;
return v.hx()==RT(0) && v.hy()==RT(0) && v.hz()==RT(0);
return v.hx() == RT(0) && v.hy() == RT(0) && v.hz() == RT(0);
}
template <class K>
typename K::RT
wdot(const typename K::Vector_3 &u,
@ -93,9 +84,6 @@ wdot(const typename K::Point_3 &p,
return wdot_tag(p, q, r, k, tag);
}
template <class K>
typename K::Vector_3
wcross(const typename K::Vector_3 &u,
@ -109,7 +97,6 @@ wcross(const typename K::Vector_3 &u,
u.hx()*v.hy() - u.hy()*v.hx());
}
template <class K>
inline
bool
@ -178,20 +165,10 @@ is_obtuse_angle(const typename K::Point_3 &p,
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) < RT(0) ;
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3 & pt1,
const typename K::Point_3 & pt2,
const K& k)
{
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,
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)
@ -206,8 +183,8 @@ squared_distance_to_plane_RT(const typename K::Vector_3 & normal,
template <class K>
typename K::FT
squared_distance_to_plane(const typename K::Vector_3 & normal,
const typename K::Vector_3 & diff,
squared_distance_to_plane(const typename K::Vector_3& normal,
const typename K::Vector_3& diff,
const K& k)
{
typedef typename K::RT RT;
@ -219,8 +196,8 @@ squared_distance_to_plane(const typename K::Vector_3 & normal,
template <class K>
void
squared_distance_to_line_RT(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff,
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)
@ -233,8 +210,8 @@ squared_distance_to_line_RT(const typename K::Vector_3 & dir,
template <class K>
typename K::FT
squared_distance_to_line(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff,
squared_distance_to_line(const typename K::Vector_3& dir,
const typename K::Vector_3& diff,
const K& k)
{
typedef typename K::RT RT;
@ -271,7 +248,6 @@ same_direction_tag(const typename K::Vector_3 &u,
}
}
template <class K>
inline
bool
@ -299,7 +275,6 @@ same_direction_tag(const typename K::Vector_3 &u,
}
}
template <class K>
inline
bool
@ -312,70 +287,19 @@ same_direction(const typename K::Vector_3 &u,
return same_direction_tag(u, v, k, tag);
}
template <class K>
inline
typename K::RT
distance_measure_sub(typename K::RT startwdist, typename K::RT endwdist,
const typename K::Vector_3 &start,
const typename K::Vector_3 &end,
const K&)
{
return CGAL_NTS abs(wmult((K*)0, startwdist, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwdist, start.hw()));
}
} // namespace internal
} // namespace CGAL
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt1,
const Point_3<K> & pt2)
{
return internal::squared_distance(pt1,pt2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K> & pt1,
const Weighted_point_3<K> & pt2)
{
return internal::squared_distance(pt1.point(),pt2.point(), K());
}
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K> & pt1,
const Point_3<K> & pt2)
{
return internal::squared_distance(pt1.point(),pt2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt1,
const Weighted_point_3<K> & pt2)
{
return internal::squared_distance(pt1,pt2.point(), K());
}
template <class K>
inline
typename K::FT
squared_distance_to_plane(const Vector_3<K> & normal,
const Vector_3<K> & diff)
{
return internal::squared_distance_to_plane(normal, diff, K());
}
template <class K>
inline
typename K::FT
squared_distance_to_line(const Vector_3<K> & dir,
const Vector_3<K> & diff)
{
return internal::squared_distance_to_line(dir, diff, K());
}
} //namespace CGAL
#endif
#endif // CGAL_SQUARED_DISTANCE_UTILS_3_H

View File

@ -18,9 +18,31 @@
#ifndef CGAL_DISTANCE_3_H
#define CGAL_DISTANCE_3_H
#include <CGAL/squared_distance_3_0.h>
#include <CGAL/squared_distance_3_1.h>
#include <CGAL/squared_distance_3_2.h>
#include <CGAL/squared_distance_3_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/Point_3_Weighted_point_3.h>
#include <CGAL/Distance_3/Point_3_Segment_3.h>
#include <CGAL/Distance_3/Point_3_Ray_3.h>
#include <CGAL/Distance_3/Point_3_Line_3.h>
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#include <CGAL/Distance_3/Point_3_Plane_3.h>
#include <CGAL/Distance_3/Point_3_Tetrahedron_3.h>
#endif
#include <CGAL/Distance_3/Weighted_point_3_Weighted_point_3.h>
#include <CGAL/Distance_3/Segment_3_Segment_3.h>
#include <CGAL/Distance_3/Segment_3_Ray_3.h>
#include <CGAL/Distance_3/Segment_3_Line_3.h>
#include <CGAL/Distance_3/Segment_3_Plane_3.h>
#include <CGAL/Distance_3/Ray_3_Ray_3.h>
#include <CGAL/Distance_3/Ray_3_Line_3.h>
#include <CGAL/Distance_3/Ray_3_Plane_3.h>
#include <CGAL/Distance_3/Line_3_Line_3.h>
#include <CGAL/Distance_3/Line_3_Plane_3.h>
#include <CGAL/Distance_3/Triangle_3_Triangle_3.h>
#include <CGAL/Distance_3/Plane_3_Plane_3.h>
#endif // CGAL_DISTANCE_3_H

File diff suppressed because it is too large Load Diff

View File

@ -1,505 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_2_H
#define CGAL_DISTANCE_3_2_H
#include <CGAL/squared_distance_3_0.h>
#include <CGAL/squared_distance_3_1.h>
#include <CGAL/wmult.h>
#include <CGAL/Point_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Ray_3.h>
#include <CGAL/Triangle_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
bool
contains_vector(const typename K::Plane_3 &pl,
const typename K::Vector_3 &vec,
const K&)
{
typedef typename K::RT RT;
return pl.a()*vec.hx() + pl.b()*vec.hy() + pl.c() * vec.hz() == RT(0);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Point_3 & pt,
const typename K::Plane_3 & plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Vector_3 Vector_3;
Vector_3 diff = construct_vector(plane.point(), pt);
return squared_distance_to_plane(plane.orthogonal_vector(), diff, k);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Point_3 & pt,
const K& k)
{
return squared_distance(pt, plane, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Line_3 &line,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::FT FT;
if (contains_vector(plane, line.direction().vector(), k))
return squared_distance(plane, line.point(), k);
return FT(0);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & p,
const typename K::Line_3 & line,
const K& k)
{
return squared_distance(line, p, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Ray_3 &ray,
const typename K::Plane_3 &plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
const Point_3 &start = ray.start();
const Point_3 &planepoint = plane.point();
Vector_3 start_min_pp = construct_vector(planepoint, start);
Vector_3 end_min_pp = ray.direction().vector();
const Vector_3 &normal = plane.orthogonal_vector();
RT sdm_rs2pp = wdot(normal, start_min_pp, k);
RT sdm_re2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_rs2pp)) {
case -1:
if (sdm_re2pp > RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_re2pp < RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Ray_3 & ray,
const K& k)
{
return squared_distance(ray, plane, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Segment_3 &seg,
const typename K::Plane_3 &plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
const Point_3 &start = seg.start();
const Point_3 &end = seg.end();
if (start == end)
return squared_distance(start, plane, k);
const Point_3 &planepoint = plane.point();
Vector_3 start_min_pp = construct_vector(planepoint, start);
Vector_3 end_min_pp = construct_vector(planepoint, end);
const Vector_3 &normal = plane.orthogonal_vector();
RT sdm_ss2pp = wdot(normal, start_min_pp, k);
RT sdm_se2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_ss2pp)) {
case -1:
if (sdm_se2pp >= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() >= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_se2pp <= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() <= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Segment_3 & seg,
const K& k)
{
return squared_distance(seg, plane, k);
}
template <class K>
inline bool
on_left_of_triangle_edge(const typename K::Point_3 & pt,
const typename K::Vector_3 & normal,
const typename K::Point_3 & ep0,
const typename K::Point_3 & ep1,
const K& k)
{
// return true iff pt is on the negative side of the plane defined
// by (ep0, ep1) and normal
typename K::Construct_vector_3 vector;
typename K::Vector_3 edge = vector(ep0, ep1);
typename K::Vector_3 diff = vector(ep0, pt);
typedef typename K::RT RT;
const bool result =
RT(wdot(wcross(edge,
normal,
k),
diff,
k)) <= RT(0);
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>
inline typename K::FT
squared_distance_to_triangle(
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,
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.
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);
// 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>
inline typename K::FT
squared_distance(
const typename K::Point_3 & pt,
const typename K::Triangle_3 & t,
const K& k)
{
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
bool inside = false;
return squared_distance_to_triangle(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
inside,
k);
}
} // namespace internal
template <class K>
bool
contains_vector(const Plane_3<K> &pl, const Vector_3<K> &vec)
{
return internal::contains_vector(pl,vec, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Point_3<K> & pt,
const Plane_3<K> & plane)
{
return internal::squared_distance(pt, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Point_3<K> & pt)
{
return internal::squared_distance(pt, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Line_3<K> &line,
const Plane_3<K> &plane)
{
return internal::squared_distance(line, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & p,
const Line_3<K> & line)
{
return internal::squared_distance(line, p, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Ray_3<K> &ray,
const Plane_3<K> &plane)
{
return internal::squared_distance(ray, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Ray_3<K> & ray)
{
return internal::squared_distance(ray, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Segment_3<K> &seg,
const Plane_3<K> &plane)
{
return internal::squared_distance(seg, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Segment_3<K> & seg)
{
return internal::squared_distance(seg, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt,
const Triangle_3<K> & t) {
return internal::squared_distance(pt, t, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K> & t,
const Point_3<K> & pt) {
return internal::squared_distance(pt, t, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K> & p1,
const Plane_3<K> & p2) {
K k;
typename K::Construct_orthogonal_vector_3 ortho_vec =
k.construct_orthogonal_vector_3_object();
if (!internal::is_null(internal::wcross(ortho_vec(p1), ortho_vec(p2), k), k))
return typename K::FT(0);
else
return internal::squared_distance(p1.point(), p2, k);
}
} //namespace CGAL
#endif

View File

@ -1,126 +0,0 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_3_H
#define CGAL_DISTANCE_3_3_H
#include <CGAL/squared_distance_3_2.h>
#include <CGAL/Point_3.h>
#include <CGAL/Tetrahedron_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Tetrahedron_3 & t,
const typename K::Point_3 & pt,
const K& k)
{
bool on_bounded_side = true;
const typename K::Point_3 t0 = t[0];
const typename K::Point_3 t1 = t[1];
const typename K::Point_3 t2 = t[2];
const typename K::Point_3 t3 = t[3];
bool dmin_initialized = false;
typename K::FT dmin;
bool inside = false;
if(orientation(t0,t1,t2, pt) == NEGATIVE){
on_bounded_side = false;
dmin = squared_distance_to_triangle(pt, t0, t1, t2, inside, k);
dmin_initialized = true;
if(inside){
return dmin;
}
}
if(orientation(t0,t3,t1, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t0, t3, t1, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(orientation(t1,t3,t2, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t1, t3, t2, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(orientation(t2,t3,t0, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t2, t3, t0, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(on_bounded_side){
return typename K::FT(0);
}
return dmin;
}
} // namespace internal
template <class K>
typename K::FT
squared_distance(const Tetrahedron_3<K> & t,
const Point_3<K> & pt)
{
return internal::squared_distance(t,pt,K());
}
template <class K>
typename K::FT
squared_distance(const Point_3<K> & pt,
const Tetrahedron_3<K> & t)
{
return internal::squared_distance(t,pt,K());
}
} //namespace CGAL
#endif

View File

@ -1,22 +1,32 @@
// 3D distance tests.
#ifdef NDEBUG
#undef NDEBUG //this testsuite requires NDEBUG to be not defined
#endif
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Simple_homogeneous.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/squared_distance_3.h>
#include <CGAL/Random.h>
#include <CGAL/Timer.h>
// #define CGAL_USE_GTE_AS_SANITY_CHECK
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
#include <Mathematics/DistTriangle3Triangle3.h>
#include <Mathematics/DistSegmentSegment.h>
#endif
#include <vector>
#include <iostream>
#include <cassert>
#include <iostream>
const double epsilon = 0.001;
struct randomint {
struct randomint
{
randomint() ;
int get() const { return sequence[cur]; }
int next() { cur = (cur+1)%11; return get();}
int next() {
cur = (cur + 1) % 11;
return get();
}
private:
int sequence[11];
int cur;
@ -40,43 +50,32 @@ inline randomint::randomint()
randomint ri;
inline double to_nt(int d)
template <typename K>
struct Test
{
return double(d);
}
template < typename K >
struct Test {
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef CGAL::Point_3< K > P;
typedef CGAL::Line_3< K > L;
typedef CGAL::Segment_3< K > S;
typedef CGAL::Ray_3< K > R;
typedef CGAL::Triangle_3< K > T;
typedef CGAL::Plane_3< K > Pl;
typedef CGAL::Iso_cuboid_3< K > Cub;
typedef CGAL::Tetrahedron_3< K > Tet;
typedef typename K::Point_3 P;
typedef typename K::Segment_3 S;
typedef typename K::Vector_3 V;
typedef typename K::Ray_3 R;
typedef typename K::Line_3 L;
typedef typename K::Triangle_3 T;
typedef typename K::Plane_3 Pl;
typedef typename K::Tetrahedron_3 Tet;
typedef typename K::Iso_cuboid_3 Cub;
private:
CGAL::Random& r;
const double epsilon = 1e-14;
int N = 1000;
double m = 0, M = 1;
template < typename Type >
bool approx_equal_nt(const Type &t1, const Type &t2)
{
if (t1 == t2)
return true;
if (CGAL::abs(t1 - t2) / (CGAL::max)(CGAL::abs(t1), CGAL::abs(t2)) < epsilon)
return true;
std::cout << " Approximate comparison failed between : " << t1 << " and " << t2 << "\n";
return false;
}
template < typename O1, typename O2 >
void check_squared_distance(const O1& o1, const O2& o2, const FT& result)
{
assert(approx_equal_nt(CGAL::squared_distance(o1, o2), result));
assert(approx_equal_nt(CGAL::squared_distance(o2, o1), result));
}
public:
Test(CGAL::Random& r, const double epsilon) : r(r), epsilon(epsilon) { }
private:
inline RT to_nt(int d) const { return RT(d); }
P p(int x, int y, int z)
{
@ -84,34 +83,119 @@ struct Test {
return P(to_nt(x*w), to_nt(y*w), to_nt(z*w), to_nt(w));
}
P random_point() const
{
return P(r.get_double(m, M), r.get_double(m, M), r.get_double(m, M));
}
Pl pl(int a, int b, int c, int d)
{
int w = ri.next();
return Pl(to_nt(a*w), to_nt(b*w), to_nt(c*w), to_nt(d*w));
}
private:
template <typename Type>
bool are_equal(const Type& t1, const Type& t2, const bool verbose = true)
{
const FT diff = CGAL::abs(t1 - t2);
if(diff > std::numeric_limits<FT>::epsilon() &&
diff > epsilon * (CGAL::abs(t1) + CGAL::abs(t2)))
{
if(verbose)
{
std::cerr << "Approximate comparison failed (t1|t2): got " << t1 << " but expected " << t2 << std::endl;
std::cerr << "Diff: " << CGAL::abs(t1 - t2) << " vs eps: " << epsilon * (CGAL::abs(t1) + CGAL::abs(t2)) << std::endl;
}
return false;
}
return true;
}
template <typename O1, typename O2>
void check_ss_distance(const O1& o1, const O2& o2)
{
FT res = CGAL::squared_distance(o1, o2);
FT asd = compute_squared_distance_interval_between_segments(o1.source(), o1.target(),
o2.source(), o2.target(), K());
assert(res == asd);
std::cout << "input: " << o1.source() << " " << o1.target() << " " << o2.source() << " " << o2.target() << std::endl;
std::cout << "result (old) = " << res << std::endl;
std::cout << "result (new) = " << asd << std::endl;
}
void do_intersect_check(const P&, const P&) { }
template <typename O2>
void do_intersect_check(const P& p, const O2& o2)
{
if(!o2.is_degenerate() && CGAL::do_intersect(p, o2))
{
assert(are_equal(CGAL::squared_distance(p, o2), FT(0)));
assert(are_equal(CGAL::squared_distance(o2, p), FT(0)));
}
}
template <typename O1, typename O2>
void do_intersect_check(const O1& o1, const O2& o2)
{
if(!o1.is_degenerate() && !o2.is_degenerate() && CGAL::do_intersect(o1, o2))
{
assert(are_equal(CGAL::squared_distance(o1, o2), FT(0)));
assert(are_equal(CGAL::squared_distance(o2, o1), FT(0)));
}
}
template <typename O1, typename O2>
void check_squared_distance(const O1& o1, const O2& o2, const FT& expected_result)
{
const FT res_o1o2 = CGAL::squared_distance(o1, o2);
const FT res_o2o1 = CGAL::squared_distance(o2, o1);
assert(are_equal(res_o1o2, expected_result));
assert(are_equal(res_o2o1, expected_result));
do_intersect_check(o1, o2);
do_intersect_check(o1, o2);
}
template <typename O1, typename O2>
void check_squared_distance_with_bound(const O1& o1, const O2& o2, const FT& ubound)
{
const FT res_o1o2 = CGAL::squared_distance(o1, o2);
const FT res_o2o1 = CGAL::squared_distance(o2, o1);
do_intersect_check(o1, o2);
do_intersect_check(o1, o2);
assert(res_o1o2 <= ubound);
assert(res_o2o1 <= ubound);
}
private:
void P_P()
{
std::cout << "Point - Point\n";
check_squared_distance (p(0, 0, 0), p(0, 0, 0), 0);
check_squared_distance (p(1, 1, 1), p(0, 0, 0), 3);
std::cout << "Point - Point" << std::endl;
check_squared_distance(p(0, 0, 0), p(0, 0, 0), 0);
check_squared_distance(p(3, 5, 7), p(0, 0, 0), 83);
}
void P_S()
{
// Note : the values are not verified by hand
std::cout << "Point - Segment\n";
check_squared_distance (p(0, 1, 2), S(p(-3, 0, 0), p( 2, 0, 0)), 5);
check_squared_distance (p(0, 1, 2), S(p( 3, 0, 0), p( 2, 0, 0)), 9);
check_squared_distance (p(0, 1, 2), S(p( 2, 0, 0), p( 3, 0, 0)), 9);
check_squared_distance (p(6, 1, 2), S(p( 2, 0, 0), p( 3, 0, 0)), 14);
std::cout << "Point - Segment" << std::endl;
check_squared_distance(p(0, 1, 2), S{p(-3, 0, 0), p( 2, 0, 0)}, 5);
check_squared_distance(p(0, 1, 2), S{p( 3, 0, 0), p( 2, 0, 0)}, 9);
check_squared_distance(p(0, 1, 2), S{p( 2, 0, 0), p( 3, 0, 0)}, 9);
check_squared_distance(p(6, 1, 2), S{p( 2, 0, 0), p( 3, 0, 0)}, 14);
}
void P_T()
{
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);
std::cout << "Point - Triangle" << std::endl;
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);
@ -136,150 +220,475 @@ struct Test {
void S_S()
{
std::cout << "Segment - Segment\n";
check_squared_distance (S(p( -8, -7, 0), p( 11, 6, 0)), S(p(23, -27, 2), p( -17, 16, 2)), 4);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 1, 1, 2), p( 6, 1, 2)), 5);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 5);
check_squared_distance (S(p( 5, 0, 0), p( 8, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 14);
check_squared_distance (S(p( 5, 0, 0), p( 0, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 5);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 6, 1, 2), p( 8, 1, 2)), 6);
check_squared_distance (S(p( 0, 0, 0), p( 0,-3, 0)), S(p( 1, 4, 2), p( 1, 7, 2)), 21);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 8, 1, 2), p( 6, 1, 2)), 6);
check_squared_distance (S(p( 0, 0, 0), p( 0, 0, 0)), S(p( 8, 1, 2), p( 6, 1, 2)), 41);
check_squared_distance (S(p( 0, 0, 0), p( 1, 0, 0)), S(p( 2, 1, 2), p( 2, -1, 2)), 5);
check_squared_distance (S(p( 2, 0, 0), p( 0, 2, 0)), S(p( 1, 1, 4), p( 4, 0, 4)), 16);
check_squared_distance (S(p( 10, 0, 0), p( 0,10, 0)), S(p( 6, 6,20), p( 20, 0,20)), 402);
check_squared_distance (S(p(-10,-13, 0), p( 0,10, 0)), S(p(10, 5,20), p( 70,-30,20)), 524.642);
check_squared_distance (S(p( 0, 0, 0), p(30,-10, 0)), S(p(-5, 20,20), p( 40, 30,20)), 824.706);
check_squared_distance (S(p( 4, 0, 0), p(-3, -1, 0)), S(p( 1, 1, 2), p( 2, 11, 2)), 6);
check_squared_distance (S(p( 3, 4, 0), p( 7, 7, 0)), S(p( 7, 0, 2), p( 6, 5, 2)), 5);
check_squared_distance (S(p( -1, 1, 0), p( 3, 4, 0)), S(p( 7, 0, 2), p( 6, 5, 2)), 13.8462);
std::cout << "Segment - Segment" << std::endl;
// coplanar segments (hardcoded)
double z = std::sqrt(2.);
P p0{-1, 0, z};
P p1{ 1, 0, z};
// translations of (0, -1, z) -- (0, 1, z) to have all variations of x&y (<0, [0;1]; >1) in the code
for(int j=-2;j<4; j+=2)
{
for(int k=-3;k<3; k+=2)
{
P p2{j, k, z};
P p3{j, k+2, z};
// to explicit the expected distances
if(j == -2 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p3, p0));
else if(j == -2 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == -2 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p2, p0));
else if(j == 0 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 0 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 0);
else if(j == 0 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 2 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p3, p1));
else if(j == 2 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 2 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p2, p1));
}
}
for(int i=0; i<N; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
p0 = CGAL::midpoint(p0, p1);
p1 = p0 + FT(0.1) * V{p1 - p0};
p2 = p2 + V{p2 - CGAL::ORIGIN} / CGAL::approximate_sqrt(CGAL::square(p2.x()) + CGAL::square(p2.y()) + CGAL::square(p2.z()) + 3);
p3 = p3 + V{p3 - CGAL::ORIGIN} * FT(std::cos(1.3));
// degenerate inputs
check_squared_distance(S{p0, p0}, S{p0, p0}, 0); // both degen
check_squared_distance(S{p3, p3}, S{p3, p3}, 0); // both degen
check_squared_distance(S{p0, p0}, S{p0, p1}, 0); // left degen + common extremity (left)
check_squared_distance(S{p0, p0}, S{p1, p0}, 0); // left degen + common extremity (right)
check_squared_distance(S{p0, p0}, S{p2, p3}, CGAL::squared_distance(p0, S(p2, p3))); // left degen
// common extremities
check_squared_distance(S{p2, p3}, S{p2, p3}, 0); // equal segments
check_squared_distance(S{p3, p2}, S{p2, p3}, 0); // equal segments but opposite dirs
check_squared_distance(S{p2, p3}, S{p2, p1}, 0); // common generic (p2 common)
check_squared_distance(S{p2, p3}, S{p1, p2}, 0); // common generic (p2 common)
check_squared_distance(S{p2, p3}, S{p3, p1}, 0); // common generic (p3 common)
check_squared_distance(S{p2, p3}, S{p1, p3}, 0); // common generic (p3 common)
// collinear segments
const double lambda_4 = r.get_double(0, 1);
const P p4 = p2 + FT(lambda_4) * V{p3 - p2};
const double lambda_5 = r.get_double(0, 1);
const P p5 = p2 + FT(lambda_5) * V{p3 - p2};
// [p2;p3) fully contains [p4;p5]
check_squared_distance(S{p2, p3}, S{p4, p5}, 0);
check_squared_distance(S{p2, p3}, S{p5, p4}, 0);
check_squared_distance(S{p3, p2}, S{p4, p5}, 0);
check_squared_distance(S{p3, p2}, S{p4, p5}, 0);
const double lambda_6 = r.get_double(0, 1);
const P p6 = p3 + FT(lambda_6) * V{p3 - p2};
// [p2;p3] overlaps [p5;p6]
check_squared_distance(S{p2, p3}, S{p6, p5}, 0);
check_squared_distance(S{p2, p3}, S{p5, p6}, 0);
check_squared_distance(S{p3, p2}, S{p6, p5}, 0);
check_squared_distance(S{p3, p2}, S{p6, p5}, 0);
const double lambda_7 = r.get_double(1, 2);
const P p7 = p3 + FT(lambda_7) * V{p3 - p2};
// [p2;p3] disjoint && left of [p6;p7]
check_squared_distance(S{p2, p3}, S{p6, p7}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p2, p3}, S{p7, p6}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p3, p2}, S{p6, p7}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p3, p2}, S{p7, p6}, CGAL::squared_distance(p3, p6));
// Generic collinear
const double lambda_8 = r.get_double(-M, M);
const P p8 = p2 + FT(lambda_8) * V{p3 - p2};
const double lambda_9 = r.get_double(-M, M);
const P p9 = p2 + FT(lambda_9) * V{p3 - p2};
S s89(p8, p9);
S s32(p3, p2);
FT result;
if(!s89.is_degenerate() && !s32.is_degenerate()) // for do_intersect...
{
if(CGAL::do_intersect(s89, s32))
result = 0;
else
result = (std::min)(CGAL::squared_distance(p2, p8),
(std::min)(CGAL::squared_distance(p2, p9),
(std::min)(CGAL::squared_distance(p3, p8),
CGAL::squared_distance(p3, p9))));
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Segment<3, FT>, gte::Segment<3, FT> > GTE_SS_checker;
gte::Segment<3, FT> gte_s1{{p8.x(), p8.y(), p8.z()}, {p9.x(), p9.y(), p9.z()}};
gte::Segment<3, FT> gte_s2{{p3.x(), p3.y(), p3.z()}, {p2.x(), p2.y(), p2.z()}};
auto gte_res = GTE_SS_checker(gte_s1, gte_s2);
std::cout << "-------" << std::endl;
std::cout << "old: " << CGAL::internal::squared_distance_old(s89, s32, K()) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
#endif
// Because do_intersect() with constructions is likely to return 'false' even for overlaps
assert(are_equal(CGAL::squared_distance(s89, s32), result, false /*verbose*/) ||
are_equal(CGAL::squared_distance(s32, s89), FT(0)));
}
// completely generic
S s1{p0, p1}, s2{p2, p3};
do_intersect_check(s1, s2);
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Segment<3, FT>, gte::Segment<3, FT> > GTE_SS_checker;
gte::Segment<3, FT> gte_s1{{p0.x(), p0.y(), p0.z()}, {p1.x(), p1.y(), p1.z()}};
gte::Segment<3, FT> gte_s2{{p2.x(), p2.y(), p2.z()}, {p3.x(), p3.y(), p3.z()}};
auto gte_res = GTE_SS_checker(gte_s1, gte_s2);
std::cout << "dist (CGAL) : " << CGAL::squared_distance(s1, s2) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
assert(are_equal(CGAL::squared_distance(s1, s2), gte_res.sqrDistance));
#endif
}
// a few brute force checks: sample a segments and use squared_distance(P3, S3)
for(int i=0; i<10; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
S s01{p0, p1};
S s23{p2, p3};
FT upper_bound = CGAL::squared_distance(p0, p2);
V p01 = V{p0, p1} / FT(N);
for(int l=0; l<N; ++l)
{
P tp = p0 + FT(l) * p01;
FT sqd = CGAL::squared_distance(tp, s23);
if(sqd < upper_bound)
upper_bound = sqd;
}
// bit ugly, but if constructions are not exact, building `tp` introduces some error
if(epsilon != 0)
upper_bound *= (1 + 1e-10);
check_squared_distance_with_bound(s01, s23, upper_bound);
}
}
void P_R()
{
// Note : the value is not verified by hand
std::cout << "Point - Ray\n";
check_squared_distance (p( -8, -7, 0), R(p(23, -27, 2), p( -17, 16, 2)), 86.3685);
std::cout << "Point - Ray" << std::endl;
check_squared_distance_with_bound(p( -8, -7, 0), R{p(23, -27, 2), p( -17, 16, 2)}, 86.368512613);
}
void R_R()
{
// Note : the values are not verified by hand
std::cout << "Ray - Ray\n";
check_squared_distance (R(p( 0, 0, 30), p( 0, 30, 30)), R(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
check_squared_distance (R(p( 1, 0, 0), p( 0, 0, 0)), R(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (R(p( 0, 0, 0), p( 1, 0, 0)), R(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Ray - Ray" << std::endl;
check_squared_distance_with_bound(R{p( 0, 0, 30), p( 0, 30, 30)}, R{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
check_squared_distance(R{p( 1, 0, 0), p( 0, 0, 0)}, R{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(R{p( 0, 0, 0), p( 1, 0, 0)}, R{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void S_R()
{
// Note : the values are not verified by hand
std::cout << "Segment - Ray\n";
check_squared_distance (S(p( 0, 0, 30), p( 0, 30, 30)), R(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
std::cout << "Segment - Ray" << std::endl;
check_squared_distance_with_bound(S{p( 0, 0, 30), p( 0, 30, 30)}, R{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
}
void R_L()
{
// Note : the values are not verified by hand
std::cout << "Ray - Line\n";
check_squared_distance (R(p(10, 0, 0), p( 20, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 109);
check_squared_distance (R(p( 0, 0, 30), p( 0, 30, 30)), L(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
check_squared_distance (R(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (R(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Ray - Line" << std::endl;
check_squared_distance_with_bound(R{p( 0, 0, 30), p( 0, 30, 30)}, L{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
check_squared_distance(R{p(10, 0, 0), p( 20, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 109);
check_squared_distance(R{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(R{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void P_L()
{
std::cout << "Point - Line\n";
check_squared_distance (p( 0, 1, 2), L(p( 2, 0, 0), p( 3, 0, 0)), 5);
check_squared_distance (p( 0, 0, 2), L(p( 0, 0, 0), p( 1, 2, 0)), 4);
std::cout << "Point - Line" << std::endl;
check_squared_distance(p( 0, 1, 2), L{p( 2, 0, 0), p( 3, 0, 0)}, 5);
check_squared_distance(p( 0, 0, 2), L{p( 0, 0, 0), p( 1, 2, 0)}, 4);
}
void S_L()
{
// Note : the values are not verified by hand
std::cout << "Segment - Line\n";
check_squared_distance (S(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (S(p(-90, 0, 0), p(-10, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 109);
check_squared_distance (S(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Segment - Line" << std::endl;
check_squared_distance(S{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(S{p(-90, 0, 0), p(-10, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 109);
check_squared_distance(S{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void L_L()
{
// Note : the values are not verified by hand
std::cout << "Line - Line\n";
check_squared_distance (L(p(-10, 0, 0), p(-90, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 9);
check_squared_distance (L(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (L(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Line - Line" << std::endl;
check_squared_distance(L{p(-10, 0, 0), p(-90, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 9);
check_squared_distance(L{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(L{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void P_Pl()
{
std::cout << "Point - Plane\n";
check_squared_distance (p(2, 5, 3), Pl(0, 1, 0, 0), 25);
std::cout << "Point - Plane" << std::endl;
check_squared_distance(p(2, 5, 3), Pl(0, 1, 0, 0), 25);
}
void S_Pl()
{
std::cout << "Segment - Plane\n";
check_squared_distance (S(p(2, -3, 3), p( 3,-7, 4)), pl(0, 1, 0, 0), 9);
std::cout << "Segment - Plane" << std::endl;
check_squared_distance(S{p(2, -3, 3), p( 3,-7, 4)}, pl(0, 1, 0, 0), 9);
}
void R_Pl()
{
std::cout << "Ray - Plane\n";
check_squared_distance (R(p(2, -4, 3), p( 3,-4, 4)), Pl(0, 1, 0, 0), 16);
check_squared_distance (R(p(2, -4, 3), p( 3, 4, 4)), Pl(0, 1, 0, 0), 0);
check_squared_distance (R(p(2, -4, 3), p( 3,-8, 4)), Pl(0, 1, 0, 0), 16);
std::cout << "Ray - Plane" << std::endl;
check_squared_distance(R{p(2, -4, 3), p( 3,-4, 4)}, Pl(0, 1, 0, 0), 16);
check_squared_distance(R{p(2, -4, 3), p( 3, 4, 4)}, Pl(0, 1, 0, 0), 0);
check_squared_distance(R{p(2, -4, 3), p( 3,-8, 4)}, Pl(0, 1, 0, 0), 16);
}
void L_Pl()
{
std::cout << "Line - Plane\n";
check_squared_distance (L(p(2, -4, 3), p( 3,-4, 4)), Pl(0, 1, 0, 0), 16);
check_squared_distance (L(p(2, -4, 3), p( 3, 4, 4)), Pl(0, 1, 0, 0), 0);
check_squared_distance (L(p(2, -4, 3), p( 3,-8, 4)), Pl(0, 1, 0, 0), 0);
std::cout << "Line - Plane" << std::endl;
check_squared_distance(L{p(2, -4, 3), p( 3,-4, 4)}, Pl(0, 1, 0, 0), 16);
check_squared_distance(L{p(2, -4, 3), p( 3, 4, 4)}, Pl(0, 1, 0, 0), 0);
check_squared_distance(L{p(2, -4, 3), p( 3,-8, 4)}, Pl(0, 1, 0, 0), 0);
}
void Pl_Pl()
{
std::cout << "Plane - Plane\n";
std::cout << "Plane - Plane" << std::endl;
Pl p1(0, 1, 0, 0);
typename K::Vector_3 v = -p1.orthogonal_vector();
v /= CGAL::sqrt(v.squared_length());
v /= CGAL::approximate_sqrt(v.squared_length());
Pl p2 = Pl(0,-1,0,6);
check_squared_distance (p1,p2, 36);
check_squared_distance (Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0);
check_squared_distance(p1,p2, 36);
check_squared_distance(Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0);
}
void T_T()
{
std::cout << "Triangle - Triangle" << std::endl;
// min between vertices (hardcoded)
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(0,0,2), p(-1,0,2), p(0,-1,2)}, 4);
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(-1,0,2), p(0,0,2), p(0,-1,2)}, 4);
check_squared_distance(T{p(1,2,3), P{4.2,5.3,-6}, p(7,-8,9)},
T{P{10.1, 12, -10}, p(15, 14, -12), p(19, 45, -20)},
CGAL::squared_distance(P{4.2,5.3,-6}, P{10.1, 12, -10}));
// min vertex-edge (hardcoded)
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(1,1,0), p(2,1,0), p(1,2,0)}, 0.5);
check_squared_distance(T{p(0,0,0), p(2,0,0), p(0,2,0)}, T{p(0,-1,1), p(2,0,1), p(2,-1,1)}, 1);
for(int i=0; i<N; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
P p4 = random_point();
P p5 = random_point();
// these are still exact with EPECK
p0 = CGAL::midpoint(p0, p1);
p1 = p0 + FT(0.1) * V{p1 - p0};
p2 = p2 + V{p2 - p0} / FT(CGAL_PI);
// this is still exact with EPECK_with_sqrt
p4 = p4 + V{p4 - CGAL::ORIGIN} / CGAL::approximate_sqrt(CGAL::square(p4.x()) + CGAL::square(p4.y()) + CGAL::square(p4.z()) + 3);
p5 = p5 + V{p5 - CGAL::ORIGIN} * FT(std::cos(1.3));
// degenerate inputs
check_squared_distance(T{p3, p3, p3}, T{p3, p3, p3}, 0); // both degen
check_squared_distance(T{p0, p0, p0}, T{p3, p3, p3}, CGAL::squared_distance(p0, p3)); // both degen
check_squared_distance(T{p0, p0, p0}, T{p0, p0, p3}, 0); // single degen and common edge
check_squared_distance(T{p0, p0, p0}, T{p3, p0, p0}, 0);
check_squared_distance(T{p0, p0, p0}, T{p0, p3, p0}, 0);
check_squared_distance(T{p0, p0, p0}, T{p0, p3, p4}, 0); // single degen and common vertex
check_squared_distance(T{p0, p0, p0}, T{p3, p0, p4}, 0);
check_squared_distance(T{p0, p0, p0}, T{p3, p4, p0}, 0);
// degen into point & degen into segment
check_squared_distance(T{p1, p1, p1}, T{p4, p3, p3}, CGAL::squared_distance(p1, S{p3, p4}));
check_squared_distance(T{p5, p5, p5}, T{p3, p3, p4}, CGAL::squared_distance(p5, S{p3, p4}));
// both degen into segment
check_squared_distance(T{p0, p1, p0}, T{p3, p3, p4}, CGAL::squared_distance(S{p0, p1}, S{p3, p4}));
check_squared_distance(T{p5, p5, p4}, T{p4, p3, p3}, CGAL::squared_distance(S{p5, p4}, S{p3, p4}));
// common vertex
check_squared_distance(T{p0, p1, p2}, T{p0, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p2}, 0);
// common edge
check_squared_distance(T{p0, p1, p2}, T{p0, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p0, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p1, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p4, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p2, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p1, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p4, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p0, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p2, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p4, p0}, 0);
// same triangle
check_squared_distance(T{p0, p1, p2}, T{p0, p1, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p2, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p0, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p1, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p2, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p0, p2}, 0);
// vertex on triangle
double lambda = r.get_double(0, 1);
double mu = r.get_double(0, 1 - lambda);
const P bp = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p4, bp}, 0);
// edge on triangle
lambda = r.get_double(0, 1);
mu = r.get_double(0, 1 - lambda);
P bp2 = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, bp2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp, p4, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, p4, bp}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp2, bp}, 0);
// part of the edge crossing the triangle
lambda = r.get_double(-1, 1);
mu = r.get_double(-1, 1);
bp2 = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, bp2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp, p4, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, p4, bp}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp2, bp}, 0);
// generic triangles
T tr1{p0, p1, p2}, tr2{p3, p4, p5};
do_intersect_check(tr1, tr2);
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Triangle3<FT>, gte::Triangle3<FT> > GTE_TT_checker;
gte::Triangle3<FT> gte_tr1{{p0.x(), p0.y(), p0.z()}, {p1.x(), p1.y(), p1.z()}, {p2.x(), p2.y(), p2.z()}};
gte::Triangle3<FT> gte_tr2{{p3.x(), p3.y(), p3.z()}, {p4.x(), p4.y(), p4.z()}, {p5.x(), p5.y(), p5.z()}};
auto gte_res = GTE_TT_checker(gte_tr1, gte_tr2);
std::cout << "dist (CGAL) : " << CGAL::squared_distance(tr1, tr2) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
std::cout << "diff CGAL GTE : " << (gte_res.sqrDistance - CGAL::squared_distance(tr1, tr2)) << std::endl;
// don't assert on purpose, GTE has slightly (10^-30 different results, even with an exact NT)
are_equal(CGAL::squared_distance(tr1, tr2), gte_res.sqrDistance);
#endif
}
}
public:
void run()
{
std::cout << "3D Distance tests\n";
std::cout << "Kernel: " << typeid(K).name() << std::endl;
P_P();
P_S();
P_T();
P_Tet();
S_S();
P_R();
R_R();
S_R();
R_L();
P_L();
S_L();
L_L();
P_T();
P_Pl();
P_Tet();
S_S();
S_R();
S_L();
S_Pl();
R_R();
R_L();
R_Pl();
L_L();
L_Pl();
T_T();
Pl_Pl();
}
};
int main()
{
Test< CGAL::Simple_cartesian<double> >().run();
Test< CGAL::Simple_homogeneous<double> >().run();
// TODO : test more kernels.
std::cout.precision(17);
std::cerr.precision(17);
std::cout << "3D Distance tests" << std::endl;
CGAL::Random r;
std::cout << "random seed = " << r.get_seed() << std::endl;
// @todo Some tests are too difficult for these kernels
// Test<CGAL::Simple_cartesian<double> >(r, 1e-5).run();
// Test<CGAL::Simple_homogeneous<double> >(r, 1e-5).run();
// Test<CGAL::Simple_cartesian<CGAL::Interval_nt<true> > >(r, 1e-5).run();
Test<CGAL::Homogeneous<CGAL::Epeck_ft> >(r, 0).run();
const double epick_eps = 10 * std::numeric_limits<double>::epsilon();
Test<CGAL::Exact_predicates_inexact_constructions_kernel>(r, epick_eps).run();
Test<CGAL::Exact_predicates_exact_constructions_kernel>(r, 0).run();
std::cout << "Done!" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -17,11 +17,11 @@
#ifndef CGAL_INTERSECTIONS_2_CIRCLE_2_CIRCLE_2_H
#define CGAL_INTERSECTIONS_2_CIRCLE_2_CIRCLE_2_H
#include <CGAL/Circle_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Circle_2.h>
namespace CGAL {
namespace Intersections {
namespace internal {

View File

@ -18,10 +18,11 @@
#ifndef CGAL_INTERSECTIONS_2_CIRCLE_2_LINE_2_H
#define CGAL_INTERSECTIONS_2_CIRCLE_2_LINE_2_H
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Line_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/Intersection_traits_2.h>
namespace CGAL {
namespace Intersections {

View File

@ -13,10 +13,11 @@
#ifndef CGAL_INTERSECTIONS_2_CIRCLE_2_RAY_2_H
#define CGAL_INTERSECTIONS_2_CIRCLE_2_RAY_2_H
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/Intersection_traits_2.h>
namespace CGAL {
namespace Intersections {

View File

@ -13,10 +13,11 @@
#ifndef CGAL_INTERSECTIONS_2_CIRCLE_2_SEGMENT_2_H
#define CGAL_INTERSECTIONS_2_CIRCLE_2_SEGMENT_2_H
#include <CGAL/Distance_2/Point_2_Segment_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/Intersection_traits_2.h>
namespace CGAL {
namespace Intersections {

View File

@ -13,10 +13,12 @@
#ifndef CGAL_INTERSECTIONS_2_CIRCLE_2_TRIANGLE_2_H
#define CGAL_INTERSECTIONS_2_CIRCLE_2_TRIANGLE_2_H
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Triangle_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/Intersection_traits_2.h>
namespace CGAL {
namespace Intersections {

View File

@ -18,8 +18,8 @@
#ifndef CGAL_INTERSECTIONS_2_INTERNAL_STRAIGHT_2_H
#define CGAL_INTERSECTIONS_2_INTERNAL_STRAIGHT_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Intersections_2/Line_2_Line_2.h>
#include <CGAL/squared_distance_utils.h>
#include <CGAL/Kernel/global_functions_internal_2.h>
namespace CGAL {

View File

@ -22,6 +22,7 @@
#include <CGAL/Intersections_2/Line_2_Line_2.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Algebraic_structure_traits.h>
#include <CGAL/Kernel/global_functions_2.h>
namespace CGAL {

View File

@ -30,8 +30,7 @@ In 2D, the types `Type1` and `Type2` can be any of the following:
as well as any combination of `Kernel::Point_2` and `Kernel::Weighted_point_2`
In 3D, the types `Type1` and `Type2` can be any of the
following:
In 3D, the types `Type1` and `Type2` can be any of the following:
- `Point_3`
- `Line_3`
@ -39,9 +38,12 @@ following:
- `Segment_3`
- `Plane_3`
as well as combinations `Point_3`/`Triangle_3`,
and `Weighted_point_3`/`Triangle_3`, as well as `Point_3`/`Tetrahedron_3`,
and `Weighted_point_3`/`Tetrahedron_3`
as well as the following combinations:
- `Point_3`/`Triangle_3`
- `Point_3`/`Tetrahedron_3`
- `Weighted_point_3`/`Triangle_3`
- `Weighted_point_3`/`Tetrahedron_3`
- `Triangle_3`/`Triangle_3`
\sa `compare_distance_to_point_grp`
\sa `compare_signed_distance_to_line_grp`

View File

@ -16,7 +16,7 @@
#include <CGAL/license/Mesh_3.h>
#include <CGAL/Mesh_3/search_for_connected_components_in_labeled_image.h>
#include <CGAL/Mesh_3/squared_distance_Point_3_Triangle_3.h>
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#include <CGAL/Labeled_mesh_domain_3.h>
#include <CGAL/make_mesh_3.h>

View File

@ -16,7 +16,6 @@
#include <CGAL/license/Mesh_3.h>
#include <CGAL/squared_distance_3_2.h>
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#endif // CGAL_SQUARED_DISTANCE_POINT_3_TRIANGLE_3_H

View File

@ -20,7 +20,7 @@
#include <CGAL/Homogeneous.h>
#include <CGAL/Point_2.h>
#include <CGAL/Intersections_2/Line_2_Line_2.h>
#include <CGAL/squared_distance_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/number_utils.h>
#include <CGAL/Nef_polynomial.h>
#undef CGAL_NEF_DEBUG

View File

@ -19,7 +19,6 @@
#include <CGAL/basic.h>
#include <CGAL/Unique_hash_map.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/compare_vertices.h>
#include <list>
#include <queue>

View File

@ -19,7 +19,6 @@
#include <CGAL/basic.h>
#include <CGAL/Unique_hash_map.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/compare_vertices.h>
#include <list>
#include <queue>

View File

@ -1,6 +1,5 @@
Algebraic_foundations
Circulator
Distance_2
Filtered_kernel
Hash_map
Installation

View File

@ -1,7 +1,8 @@
#ifndef POLYHEDRON_DEMO_STATISTICS_HELPERS_H
#define POLYHEDRON_DEMO_STATISTICS_HELPERS_H
#include <CGAL/squared_distance_3_0.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/Point_3_Line_3.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
#include <boost/accumulators/accumulators.hpp>

View File

@ -15,10 +15,10 @@
#include <CGAL/boost/graph/properties.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Unique_hash_map.h>
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/number_utils.h>
#include <memory>
#include <CGAL/boost/graph/internal/Has_member_id.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#define CGAL_HDS_PARAM_ template < class Traits, class Items, class Alloc> class HDS