re-add Construct_projected_point_2 for 2d closest point query

This commit is contained in:
Sven Oesau 2024-03-21 12:03:57 +01:00
parent 8059230084
commit 86fe47c7f7
2 changed files with 208 additions and 0 deletions

View File

@ -3278,6 +3278,8 @@ namespace CartesianKernelFunctors {
{ {
typedef typename K::Point_2 Point_2; typedef typename K::Point_2 Point_2;
typedef typename K::Line_2 Line_2; typedef typename K::Line_2 Line_2;
typedef typename K::Segment_2 Segment_2;
typedef typename K::Triangle_2 Triangle_2;
public: public:
typedef Point_2 result_type; typedef Point_2 result_type;
@ -3289,6 +3291,14 @@ namespace CartesianKernelFunctors {
line_project_pointC2(l.a(), l.b(), l.c(), p.x(), p.y(), x, y); line_project_pointC2(l.a(), l.b(), l.c(), p.x(), p.y(), x, y);
return construct_point_2(x, y); return construct_point_2(x, y);
} }
Point_2
operator()(const Segment_2& s, const Point_2& p) const
{ return CommonKernelFunctors::Construct_projected_point_2<K>()(s, p, K()); }
Point_2
operator()(const Triangle_2& t, const Point_2& p) const
{ return CommonKernelFunctors::Construct_projected_point_2<K>()(t, p, K()); }
}; };

View File

@ -2872,6 +2872,204 @@ namespace CommonKernelFunctors {
{ {
return v.rep().cartesian_end(); return v.rep().cartesian_end();
} }
}; template <typename K>
class Construct_projected_point_2
{
bool
is_inside_triangle_2_aux(
const typename K::Point_2& p1,
const typename K::Point_2& p2,
const typename K::Point_2& q,
typename K::Point_2& result,
bool& outside,
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::Construct_projected_point_2 projection =
k.construct_projected_point_2_object();
typename K::Construct_line_2 line =
k.construct_line_2_object();
typename K::Compute_scalar_product_2 scalar_product =
k.compute_scalar_product_2_object();
typename K::Construct_direction_2 direction =
k.construct_direction_2_object();
typename K::Construct_perpendicular_direction_2 perpendicular =
k.construct_perpendicular_direction_2_object();
// Check whether the point is cw or ccw with the triangle side (p1,p2)
Vector_2 orth = vector(p1, p2);
if (scalar_product(vector(p1, q), vector(perpendicular(direction(orth), CGAL::COUNTERCLOCKWISE))) < FT(0))
{
if (scalar_product(vector(p1, q), vector(p1, p2)) >= FT(0)
&& scalar_product(vector(p2, q), vector(p2, p1)) >= FT(0))
{
result = projection(line(p1, p2), q);
return true;
}
outside = true;
}
return false;
}
/**
* Returns the nearest point of p1,p2,p3 from origin
* @param origin the origin point
* @param p1 the first point
* @param p2 the second point
* @param p3 the third point
* @param k the kernel
* @return the nearest point from origin
*/
typename K::Point_2
nearest_point_2(const typename K::Point_2& origin,
const typename K::Point_2& p1,
const typename K::Point_2& p2,
const typename K::Point_2& p3,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_distance =
k.compute_squared_distance_2_object();
const FT dist_origin_p1 = sq_distance(origin, p1);
const FT dist_origin_p2 = sq_distance(origin, p2);
const FT dist_origin_p3 = sq_distance(origin, p3);
if (dist_origin_p2 >= dist_origin_p1
&& dist_origin_p3 >= dist_origin_p1)
{
return p1;
}
if (dist_origin_p3 >= dist_origin_p2)
{
return p2;
}
return p3;
}
/**
* @brief returns true if p is inside triangle t. If p is not inside t,
* result is the nearest point of t from p.
* @param p the reference point
* @param t the triangle
* @param result if p is not inside t, the nearest point of t from p
* @param k the kernel
* @return true if p is inside t
*/
bool
is_inside_triangle_2(const typename K::Point_2& p,
const typename K::Triangle_2& t,
typename K::Point_2& result,
const K& k)
{
typedef typename K::Point_2 Point_2;
typename K::Construct_vertex_2 vertex_on =
k.construct_vertex_2_object();
const Point_2& t0 = vertex_on(t, 0);
const Point_2& t1 = vertex_on(t, 1);
const Point_2& t2 = vertex_on(t, 2);
bool outside = false;
if (is_inside_triangle_2_aux(t0, t1, p, result, outside, k)
|| is_inside_triangle_2_aux(t1, t2, p, result, outside, k)
|| is_inside_triangle_2_aux(t2, t0, p, result, outside, k))
{
return false;
}
if (outside)
{
result = nearest_point_2(p, t0, t1, t2, k);
return false;
}
else
{
return true;
}
}
public:
typename K::Point_2
operator()(const typename K::Triangle_2& triangle,
const typename K::Point_2& origin,
const K& k)
{
typedef typename K::Point_2 Point_2;
typename K::Construct_vertex_2 vertex_on;
typename K::Construct_segment_2 segment;
// Check if triangle is degenerated to call segment operator.
const Point_2& t0 = vertex_on(triangle, 0);
const Point_2& t1 = vertex_on(triangle, 1);
const Point_2& t2 = vertex_on(triangle, 2);
if (t0 == t1)
return (*this)(segment(t1, t2), origin, k);
if (t1 == t2)
return (*this)(segment(t2, t0), origin, k);
if (t2 == t0)
return (*this)(segment(t0, t1), origin, k);
Point_2 moved_point;
bool inside = is_inside_triangle_2(origin, triangle, moved_point, k);
// If proj is inside triangle, return it
if (inside)
{
return origin;
}
// Else return the constructed point
return moved_point;
}
typename K::Point_2
operator()(const typename K::Segment_2& s,
const typename K::Point_2& query,
const K& k) {
typename K::Construct_vector_2 vector =
k.construct_vector_2_object();
typename K::Compute_scalar_product_2 scalar_product =
k.compute_scalar_product_2_object();
typename K::Construct_scaled_vector_2 scaled_vector =
k.construct_scaled_vector_2_object();
const typename K::Point_2& a = s.source();
const typename K::Point_2& b = s.target();
const typename K::Vector_2 d = vector(a, b);
typename K::FT sqlen = scalar_product(d, d);
// Degenerate segment
if (is_zero(sqlen))
return a;
const typename K::Vector_2 p = vector(a, query);
typename K::FT proj = (scalar_product(p, d)) / sqlen;
if (!is_positive(proj))
return a;
if (proj >= 1.0)
return b;
typename K::Construct_point_2 construct_point_2;
return construct_point_2(a + scaled_vector(d, proj));
}
}; };
template <typename K> template <typename K>