mirror of https://github.com/CGAL/cgal
114 lines
3.2 KiB
C++
114 lines
3.2 KiB
C++
// Copyright (c) 2009 INRIA Sophia-Antipolis (France).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public License as
|
|
// published by the Free Software Foundation; either version 3 of the License,
|
|
// or (at your option) any later version.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
//
|
|
// Author(s) : Camille Wormser, Stephane Tayeb, Pierre Alliez
|
|
//
|
|
|
|
#ifndef CGAL_KERNEL_NEAREST_POINT_SEGMENT_3_H_
|
|
#define CGAL_KERNEL_NEAREST_POINT_SEGMENT_3_H_
|
|
|
|
#include <CGAL/kernel_basic.h>
|
|
#include <CGAL/enum.h>
|
|
|
|
|
|
namespace CGAL {
|
|
|
|
|
|
namespace internal {
|
|
|
|
/**
|
|
* @brief returns true if p is inside segment s. If p is not inside s,
|
|
* result is the nearest point of s from p. WARNING: it is assumed that
|
|
* t and p are on the same line.
|
|
* @param query the query point
|
|
* @param s the segment
|
|
* @param closest_point_on_segment if query is not inside s, the nearest point of s from p
|
|
* @param k the kernel
|
|
* @return true if p is inside s
|
|
*/
|
|
template <class K>
|
|
inline
|
|
bool
|
|
is_inside_segment_3(const typename K::Point_3& query,
|
|
const typename K::Segment_3 & s,
|
|
typename K::Point_3& closest_point_on_segment,
|
|
const K& k)
|
|
{
|
|
typename K::Construct_vector_3 vector =
|
|
k.construct_vector_3_object();
|
|
typename K::Construct_vertex_3 vertex_on =
|
|
k.construct_vertex_3_object();
|
|
typename K::Compute_scalar_product_3 scalar_product =
|
|
k.compute_scalar_product_3_object();
|
|
|
|
typedef typename K::FT FT;
|
|
typedef typename K::Point_3 Point;
|
|
|
|
const Point& a = vertex_on(s, 0);
|
|
const Point& b = vertex_on(s, 1);
|
|
if( scalar_product(vector(a,b), vector(a, query)) < FT(0) )
|
|
{
|
|
closest_point_on_segment = a;
|
|
return false;
|
|
}
|
|
if( scalar_product(vector(b,a), vector(b, query)) < FT(0) )
|
|
{
|
|
closest_point_on_segment = b;
|
|
return false;
|
|
}
|
|
|
|
// query is on segment
|
|
return true;
|
|
}
|
|
|
|
template <class K>
|
|
typename K::Point_3
|
|
nearest_point_3(const typename K::Point_3& query,
|
|
const typename K::Segment_3& segment,
|
|
const K& k)
|
|
{
|
|
typedef typename K::Point_3 Point_3;
|
|
|
|
typename K::Construct_projected_point_3 projection =
|
|
k.construct_projected_point_3_object();
|
|
typename K::Is_degenerate_3 is_degenerate =
|
|
k.is_degenerate_3_object();
|
|
typename K::Construct_vertex_3 vertex =
|
|
k.construct_vertex_3_object();
|
|
|
|
if(is_degenerate(segment))
|
|
return vertex(segment, 0);
|
|
|
|
// Project query on segment supporting line
|
|
const Point_3 proj = projection(segment.supporting_line(), query);
|
|
|
|
Point_3 closest_point_on_segment;
|
|
bool inside = is_inside_segment_3(proj,segment,closest_point_on_segment,k);
|
|
|
|
// If proj is inside segment, returns it
|
|
if ( inside )
|
|
return proj;
|
|
|
|
// Else returns the constructed point
|
|
return closest_point_on_segment;
|
|
}
|
|
|
|
} } // end namespace CGAL::internal
|
|
|
|
#endif // CGAL_KERNEL_NEAREST_POINT_SEGMENT_3_H_
|