Cleaned up

This commit is contained in:
Efi Fogel 2024-11-13 18:35:18 +02:00
parent db4404f0cc
commit ddeaeb497a
2 changed files with 225 additions and 294 deletions

View File

@ -8,8 +8,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
// //
// //
// Author(s) : Idit Haran <haranidi@post.tau.ac.il> // Author(s) : Idit Haran <haranidi@post.tau.ac.il>
// Ron Wein <wein@post.tau.ac.il> // Ron Wein <wein@post.tau.ac.il>
#ifndef CGAL_ARR_LANDMARKS_POINT_LOCATION_H #ifndef CGAL_ARR_LANDMARKS_POINT_LOCATION_H
#define CGAL_ARR_LANDMARKS_POINT_LOCATION_H #define CGAL_ARR_LANDMARKS_POINT_LOCATION_H
@ -42,44 +42,44 @@ namespace CGAL {
* Generator is a class that generates the set of landmarks. * Generator is a class that generates the set of landmarks.
*/ */
template <class Arrangement_, template <typename Arrangement_,
class Generator_ = Arr_landmarks_vertices_generator<Arrangement_> > typename Generator_ = Arr_landmarks_vertices_generator<Arrangement_>>
class Arr_landmarks_point_location class Arr_landmarks_point_location {
{
public: public:
typedef Arrangement_ Arrangement_2; using Arrangement_2 = Arrangement_;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2; using Generator = Generator_;
typedef Generator_ Generator; using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
typedef typename Arrangement_2::Face_const_handle Face_const_handle; using Face_const_handle = typename Arrangement_2::Face_const_handle;
typedef typename Arrangement_2::Vertex_const_iterator Vertex_const_iterator; using Vertex_const_iterator = typename Arrangement_2::Vertex_const_iterator;
typedef typename Arrangement_2::Halfedge_const_iterator using Halfedge_const_iterator =
Halfedge_const_iterator; typename Arrangement_2::Halfedge_const_iterator;
typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator
Halfedge_around_vertex_const_circulator;
typedef typename Arrangement_2::Ccb_halfedge_const_circulator
Ccb_halfedge_const_circulator;
typedef typename Arrangement_2::Outer_ccb_const_iterator
Outer_ccb_const_iterator;
typedef typename Arrangement_2::Inner_ccb_const_iterator
Inner_ccb_const_iterator;
typedef typename Arrangement_2::Isolated_vertex_const_iterator
Isolated_vertex_const_iterator;
typedef typename Arrangement_2::Point_2 Point_2; using Halfedge_around_vertex_const_circulator =
typedef typename Arrangement_2::X_monotone_curve_2 X_monotone_curve_2; typename Arrangement_2::Halfedge_around_vertex_const_circulator;
using Ccb_halfedge_const_circulator =
typename Arrangement_2::Ccb_halfedge_const_circulator;
using Outer_ccb_const_iterator =
typename Arrangement_2::Outer_ccb_const_iterator;
using Inner_ccb_const_iterator =
typename Arrangement_2::Inner_ccb_const_iterator;
using Isolated_vertex_const_iterator =
typename Arrangement_2::Isolated_vertex_const_iterator;
typedef Arr_point_location_result<Arrangement_2> Result; using Point_2 = typename Arrangement_2::Point_2;
typedef typename Result::Type Result_type; using X_monotone_curve_2 = typename Arrangement_2::X_monotone_curve_2;
using Result = Arr_point_location_result<Arrangement_2>;
using Result_type = typename Result::Type;
// Support cpp11::result_of // Support cpp11::result_of
typedef Result_type result_type; using result_type = Result_type;
protected: protected:
typedef Arr_traits_basic_adaptor_2<Geometry_traits_2> Traits_adaptor_2; using Traits_adaptor_2 = Arr_traits_basic_adaptor_2<Geometry_traits_2>;
/*! \struct Less_halfedge_handle /*! \struct Less_halfedge_handle
* Used to sort handles. * Used to sort handles.
@ -92,10 +92,10 @@ protected:
typedef std::set<Halfedge_const_handle, Less_halfedge_handle> Halfedge_set; typedef std::set<Halfedge_const_handle, Less_halfedge_handle> Halfedge_set;
// Data members: // Data members:
const Arrangement_2* p_arr; // The associated arrangement. const Arrangement_2* p_arr; // The associated arrangement.
const Traits_adaptor_2* m_traits; // Its associated traits object. const Traits_adaptor_2* m_traits; // Its associated traits object.
Generator* lm_gen; // The associated landmark generator. Generator* lm_gen; // The associated landmark generator.
bool own_gen; // Indicates whether the generator bool own_gen; // Indicates whether the generator
// has been locally allocated. // has been locally allocated.
template<typename T> template<typename T>
@ -103,7 +103,7 @@ protected:
inline Result_type default_result() const { return Result::default_result(); } inline Result_type default_result() const { return Result::default_result(); }
public: public:
/*! Default constructor. */ /*! constructs default. */
Arr_landmarks_point_location() : Arr_landmarks_point_location() :
p_arr(nullptr), p_arr(nullptr),
m_traits(nullptr), m_traits(nullptr),
@ -111,34 +111,32 @@ public:
own_gen(false) own_gen(false)
{} {}
/*! Constructor given an arrangement only. */ /*! constructs given an arrangement only. */
Arr_landmarks_point_location(const Arrangement_2& arr) : Arr_landmarks_point_location(const Arrangement_2& arr) :
p_arr(&arr), p_arr(&arr),
m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())), m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())),
lm_gen(new Generator(arr)), // allocate the landmarks generator. lm_gen(new Generator(arr)), // allocate the landmarks generator.
own_gen(true) own_gen(true)
{ } {}
/*! Constructor given an arrangement, and landmarks generator. */ /*! constructs given an arrangement, and landmarks generator. */
Arr_landmarks_point_location(const Arrangement_2& arr, Generator* gen) : Arr_landmarks_point_location(const Arrangement_2& arr, Generator* gen) :
p_arr(&arr), p_arr(&arr),
m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())), m_traits(static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits())),
lm_gen(gen), lm_gen(gen),
own_gen(false) own_gen(false)
{ } {}
/*! Destructor. */ /*! destructs. */
~Arr_landmarks_point_location() ~Arr_landmarks_point_location() {
{
if (own_gen) { if (own_gen) {
delete lm_gen; delete lm_gen;
lm_gen = nullptr; lm_gen = nullptr;
} }
} }
/*! Attach an arrangement object (and a generator, if supplied). */ /*! attaches an arrangement object (and a generator, if supplied). */
void attach(const Arrangement_2& arr, Generator* gen = nullptr) void attach(const Arrangement_2& arr, Generator* gen = nullptr) {
{
// Keep a pointer to the associated arrangement. // Keep a pointer to the associated arrangement.
p_arr = &arr; p_arr = &arr;
m_traits = static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits()); m_traits = static_cast<const Traits_adaptor_2*>(p_arr->geometry_traits());
@ -163,9 +161,8 @@ public:
} }
} }
/*! Detach the instance from the arrangement object. */ /*! detaches the instance from the arrangement object. */
void detach() void detach() {
{
p_arr = nullptr; p_arr = nullptr;
m_traits = nullptr; m_traits = nullptr;
@ -174,8 +171,7 @@ public:
lm_gen->detach(); lm_gen->detach();
} }
/*! /*! locates the arrangement feature containing the given point.
* Locate the arrangement feature containing the given point.
* \param p The query point. * \param p The query point.
* \return An object representing the arrangement feature containing the * \return An object representing the arrangement feature containing the
* query point. This object is either a Face_const_handle or a * query point. This object is either a Face_const_handle or a
@ -184,7 +180,7 @@ public:
result_type locate(const Point_2& p) const; result_type locate(const Point_2& p) const;
protected: protected:
/*! Walk from the given vertex to the query point. /*! walks from the given vertex to the query point.
* \param vh The given vertex handle. * \param vh The given vertex handle.
* \param p The query point. * \param p The query point.
* \param crossed_edges In/Out: The set of edges crossed so far. * \param crossed_edges In/Out: The set of edges crossed so far.
@ -196,7 +192,7 @@ protected:
const Point_2& p, const Point_2& p,
Halfedge_set& crossed_edges) const; Halfedge_set& crossed_edges) const;
/*! Locate an edge around a given vertex that is the predecessor of the /*! locates an edge around a given vertex that is the predecessor of the
* curve connecting the vertex to the query point in a clockwise order. * curve connecting the vertex to the query point in a clockwise order.
* \param vh The vertex. * \param vh The vertex.
* \param p The query point. * \param p The query point.
@ -207,7 +203,7 @@ protected:
const Point_2& p, const Point_2& p,
bool& new_vertex) const; bool& new_vertex) const;
/*! Walk from a point on a given halfedge to the query point. /*! walks from a point on a given halfedge to the query point.
* \param eh The given halfedge handle. * \param eh The given halfedge handle.
* \param np The point that the walk starts from. * \param np The point that the walk starts from.
* \param p The query point. * \param p The query point.
@ -220,7 +216,7 @@ protected:
const Point_2& np, const Point_2& np,
const Point_2& p, const Point_2& p,
Halfedge_set& crossed_edges) const; Halfedge_set& crossed_edges) const;
/*! In case the arrangement's curve contained in the segment /*! handles the arrangement curve contained in the segment
* from the nearest landmark to the query point * from the nearest landmark to the query point
* \param he The given halfedge handle. * \param he The given halfedge handle.
* \param p_is_left Is the query point the left endpoint of seg. * \param p_is_left Is the query point the left endpoint of seg.
@ -236,7 +232,7 @@ protected:
const Point_2& p, const Point_2& p,
Halfedge_set& crossed_edges) const; Halfedge_set& crossed_edges) const;
/*! Walk from a point in a face to the query point. /*! walks from a point in a face to the query point.
* \param fh A halfedge handle that points to the face. * \param fh A halfedge handle that points to the face.
* \param np The point that the walk starts from. * \param np The point that the walk starts from.
* \param p The query point. * \param p The query point.
@ -250,7 +246,7 @@ protected:
const Point_2& p, const Point_2& p,
Halfedge_set& crossed_edges) const; Halfedge_set& crossed_edges) const;
/*! Find a halfedge on the given CCB that intersects the given x-monotone /*! finds a halfedge on the given CCB that intersects the given x-monotone
* curve, connecting the current landmark to the query point. * curve, connecting the current landmark to the query point.
* \param circ The CCB circulator. * \param circ The CCB circulator.
* \param seg The segment connecting the landmark and the query point. * \param seg The segment connecting the landmark and the query point.
@ -275,7 +271,7 @@ protected:
bool& cv_is_contained_in_seg, bool& cv_is_contained_in_seg,
Vertex_const_handle& new_vertex) const; Vertex_const_handle& new_vertex) const;
/*! Return the halfedge that contains the query point. /*! returns the halfedge that contains the query point.
* \param he The halfedge handle. * \param he The halfedge handle.
* \param crossed_edges In/Out: The set of edges crossed so far. * \param crossed_edges In/Out: The set of edges crossed so far.
* \param p The query point. * \param p The query point.
@ -287,7 +283,7 @@ protected:
const Point_2& p, const Point_2& p,
bool& is_target) const; bool& is_target) const;
/*! Check whether the given curve intersects a simple segment, which connects /*! checks whether the given curve intersects a simple segment, which connects
* the current landmark to the query point, an odd number of times. * the current landmark to the query point, an odd number of times.
* \param cv The curve. * \param cv The curve.
* \param seg The segment connecting the landmark and the query point. * \param seg The segment connecting the landmark and the query point.
@ -305,7 +301,7 @@ protected:
bool& cv_is_contained_in_seg) const; bool& cv_is_contained_in_seg) const;
}; };
} //namespace CGAL } // namespace CGAL
// The member-function definitions can be found under: // The member-function definitions can be found under:
#include <CGAL/Arr_point_location/Arr_landmarks_pl_impl.h> #include <CGAL/Arr_point_location/Arr_landmarks_pl_impl.h>

View File

@ -7,16 +7,15 @@
// $Id$ // $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
// //
// Author(s) : Idit Haran <haranidi@post.tau.ac.il> // Author(s) : Idit Haran <haranidi@post.tau.ac.il>
// Ron Wein <wein@post.tau.ac.il> // Ron Wein <wein@post.tau.ac.il>
// Efi Fogel <efif@post.tau.ac.il> // Efi Fogel <efif@post.tau.ac.il>
#ifndef CGAL_ARR_LANDMARKS_PL_IMPL_H #ifndef CGAL_ARR_LANDMARKS_PL_IMPL_H
#define CGAL_ARR_LANDMARKS_PL_IMPL_H #define CGAL_ARR_LANDMARKS_PL_IMPL_H
#include <CGAL/license/Arrangement_on_surface_2.h> #include <CGAL/license/Arrangement_on_surface_2.h>
/*! \file /*! \file
* Member-function definitions for the * Member-function definitions for the
* Arr_landmarks_point_location<Arrangement, Generator> class. * Arr_landmarks_point_location<Arrangement, Generator> class.
@ -24,60 +23,59 @@
namespace CGAL { namespace CGAL {
//----------------------------------------------------------------------------- // Helper trait to check for the presence of nested Is_on_x_identification_2
// Locate the arrangement feature containing the given point. template <typename, typename = std::void_t<>>
// struct has_is_on_x_identification_2 : std::false_type {};
// Specialization if the nested type Is_on_x_identification_2 exists
template <typename T>
struct has_is_on_x_identification_2<T, std::void_t<typename T::Is_on_x_identification_2>> : std::true_type {};
/*! locates the arrangement feature containing the given point.
*/
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const {
{
// If the arrangement is empty, return its initial (empty and // If the arrangement is empty, return its initial (empty and
// non-fictitious) face. // non-fictitious) face.
if (p_arr->number_of_vertices() == 0) { if (p_arr->number_of_vertices() == 0) {
CGAL_assertion(p_arr->number_of_faces() == 1); CGAL_assertion(p_arr->number_of_faces() == 1);
Face_const_handle fh = p_arr->faces_begin(); Face_const_handle fh = p_arr->faces_begin();
return make_result(fh); return make_result(fh);
} }
// Use the generator and to find the closest landmark to the query point. // Use the generator and to find the closest landmark to the query point.
result_type lm_location_obj; result_type lm_location_obj;
const Point_2& landmark_point = lm_gen->closest_landmark(p, lm_location_obj); const Point_2& landmark_point = lm_gen->closest_landmark(p, lm_location_obj);
// If the query point and the landmark point are equal, return the landmark. // If the query point and the landmark point are equal, return the landmark.
if (m_traits->equal_2_object()(landmark_point, p)) if (m_traits->equal_2_object()(landmark_point, p)) return lm_location_obj;
return lm_location_obj;
// Walk from the nearest_vertex to the point p, using walk algorithm, // Walk from the nearest_vertex to the point p, using walk algorithm,
// and find the location of the query point p. Note that the set of edges // and find the location of the query point p. Note that the set of edges
// we have crossed so far is initially empty. // we have crossed so far is initially empty.
Halfedge_set crossed_edges; Halfedge_set crossed_edges;
result_type out_obj; result_type out_obj;
// Locate the arrangement feature that contains the landmark. // Locate the arrangement feature that contains the landmark.
const Vertex_const_handle* vh; if (const auto* v = std::get_if<Vertex_const_handle>(&lm_location_obj))
const Halfedge_const_handle* hh; out_obj = _walk_from_vertex(*v, p, crossed_edges);
const Face_const_handle* fh; else if (const auto* e = std::get_if<Halfedge_const_handle>(&lm_location_obj))
if ( ( vh = Result().template assign<Vertex_const_handle>(&lm_location_obj) ) ) out_obj = _walk_from_edge(*e, landmark_point, p, crossed_edges);
out_obj = _walk_from_vertex(*vh, p, crossed_edges); else if (const auto* f = std::get_if<Face_const_handle>(&lm_location_obj))
else if ( ( hh = Result().template assign<Halfedge_const_handle>(&lm_location_obj) ) ) out_obj = _walk_from_face(*f, landmark_point, p, crossed_edges);
out_obj = _walk_from_edge(*hh, landmark_point, p, crossed_edges);
else if ( ( fh = Result().template assign<Face_const_handle>(&lm_location_obj) ) )
out_obj = _walk_from_face(*fh, landmark_point, p, crossed_edges);
else CGAL_error_msg("lm_location_obj of an unknown type."); else CGAL_error_msg("lm_location_obj of an unknown type.");
if ( ( fh = Result().template assign<Face_const_handle>(&out_obj) ) ) { if (const auto* f = std::get_if<Face_const_handle>(&out_obj)) {
// If we reached here, we did not locate the query point in any of the // If we reached here, we did not locate the query point in any of the
// holes inside the current face, so we conclude it is contained in this // holes inside the current face, so we conclude it is contained in this
// face. // face. However, we first have to check whether the query point coincides
// However, we first have to check whether the query point coincides with // with any of the isolated vertices contained inside this face.
// any of the isolated vertices contained inside this face. auto equal = m_traits->equal_2_object();
Isolated_vertex_const_iterator iso_verts_it; for (auto iso_verts_it = (*f)->isolated_vertices_begin();
typename Traits_adaptor_2::Equal_2 equal = m_traits->equal_2_object(); iso_verts_it != (*f)->isolated_vertices_end(); ++iso_verts_it) {
for (iso_verts_it = (*fh)->isolated_vertices_begin();
iso_verts_it != (*fh)->isolated_vertices_end(); ++iso_verts_it)
{
if (equal(p, iso_verts_it->point())) { if (equal(p, iso_verts_it->point())) {
Vertex_const_handle ivh = iso_verts_it; Vertex_const_handle ivh = iso_verts_it;
return make_result(ivh); return make_result(ivh);
} }
} }
@ -86,28 +84,24 @@ Arr_landmarks_point_location<Arr, Gen>::locate(const Point_2& p) const
return out_obj; return out_obj;
} }
//----------------------------------------------------------------------------- /*! walks from a given vertex to the query point.
// Walk from a given vertex to the query point. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
_walk_from_vertex(Vertex_const_handle nearest_vertex, _walk_from_vertex(Vertex_const_handle nearest_vertex, const Point_2& p,
const Point_2& p, Halfedge_set& crossed_edges) const {
Halfedge_set& crossed_edges) const
{
Vertex_const_handle vh = nearest_vertex; Vertex_const_handle vh = nearest_vertex;
CGAL_assertion_msg(! vh->is_at_open_boundary(), CGAL_assertion_msg(! vh->is_at_open_boundary(),
"_walk_from_vertex() from a vertex at infinity."); "_walk_from_vertex() from a vertex at infinity.");
// Check if the query point p coincides with the vertex. // Check if the query point p coincides with the vertex.
if (m_traits->equal_2_object()(vh->point(), p)) if (m_traits->equal_2_object()(vh->point(), p)) return make_result(vh);
return make_result(vh);
// In case of an isolated vertex, walk to from the face that contains // In case of an isolated vertex, walk to from the face that contains
// it toward the query point. // it toward the query point.
if (vh->is_isolated()) { if (vh->is_isolated()) {
Face_const_handle fh = vh->face(); Face_const_handle fh = vh->face();
return (_walk_from_face(fh, vh->point(), p, crossed_edges)); return (_walk_from_face(fh, vh->point(), p, crossed_edges));
} }
@ -116,30 +110,29 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
Halfedge_around_vertex_const_circulator first = vh->incident_halfedges(); Halfedge_around_vertex_const_circulator first = vh->incident_halfedges();
// Create an x-monotone curve connecting the point associated with the // Create an x-monotone curve connecting the point associated with the
// vertex vp and the query point p. // vertex vp and the query point p.
const Point_2& vp = vh->point(); const Point_2& vp = vh->point();
X_monotone_curve_2 seg = X_monotone_curve_2 seg =
m_traits->construct_x_monotone_curve_2_object()(vp, p); m_traits->construct_x_monotone_curve_2_object()(vp, p);
const bool seg_dir_right = const bool seg_dir_right =
(m_traits->compare_xy_2_object()(vp, p) == SMALLER); (m_traits->compare_xy_2_object()(vp, p) == SMALLER);
Halfedge_around_vertex_const_circulator curr_iter = first; Halfedge_around_vertex_const_circulator curr_iter = first;
Halfedge_around_vertex_const_circulator next_iter = curr_iter; Halfedge_around_vertex_const_circulator next_iter = curr_iter;
++next_iter; ++next_iter;
typename Traits_adaptor_2::Is_between_cw_2 is_between_cw = auto is_between_cw = m_traits->is_between_cw_2_object();
m_traits->is_between_cw_2_object();
// Traverse the halfedges around vp until we find the pair of adjacent // Traverse the halfedges around vp until we find the pair of adjacent
// halfedges such as seg is located clockwise in between them. // halfedges such as seg is located clockwise in between them.
do { do {
bool eq_curr_iter, eq_next_iter; bool eq_curr_iter, eq_next_iter;
if (is_between_cw(seg, seg_dir_right, curr_iter->curve(), if (is_between_cw(seg, seg_dir_right, curr_iter->curve(),
(curr_iter->direction() == ARR_RIGHT_TO_LEFT), (curr_iter->direction() == ARR_RIGHT_TO_LEFT),
next_iter->curve(), next_iter->curve(),
(next_iter->direction() == ARR_RIGHT_TO_LEFT), (next_iter->direction() == ARR_RIGHT_TO_LEFT),
vp, eq_curr_iter, eq_next_iter)) vp, eq_curr_iter, eq_next_iter)) {
{
// the assumption is that each edge is crossed at most twice // the assumption is that each edge is crossed at most twice
CGAL_assertion_msg(crossed_edges.count (curr_iter) < 2, CGAL_assertion_msg(crossed_edges.count(curr_iter) < 2,
"crossed_edges should contain each halfedge at most twice."); "crossed_edges should contain each halfedge at most twice.");
CGAL_assertion_msg(crossed_edges.count (next_iter) < 2, CGAL_assertion_msg(crossed_edges.count(next_iter) < 2,
"crossed_edges should contain each halfedge at most twice."); "crossed_edges should contain each halfedge at most twice.");
crossed_edges.insert(curr_iter); crossed_edges.insert(curr_iter);
crossed_edges.insert(curr_iter->twin()); crossed_edges.insert(curr_iter->twin());
@ -158,8 +151,7 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
result_type obj = _find_face_around_vertex(vh, p, new_vertex); result_type obj = _find_face_around_vertex(vh, p, new_vertex);
if (new_vertex) { if (new_vertex) {
// We found a vertex closer to p; Continue using this vertex. // We found a vertex closer to p; Continue using this vertex.
const Vertex_const_handle* p_vh = const auto* p_vh = std::get_if<Vertex_const_handle>(&obj);
Result().template assign<Vertex_const_handle>(&obj);
CGAL_assertion(p_vh != nullptr); CGAL_assertion(p_vh != nullptr);
vh = *p_vh; vh = *p_vh;
continue; continue;
@ -167,15 +159,13 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
// If p is located on an edge or on a vertex, return the object // If p is located on an edge or on a vertex, return the object
// that wraps this arrangement feature. // that wraps this arrangement feature.
if (Result().template assign<Halfedge_const_handle>(&obj) || if (std::get_if<Halfedge_const_handle>(&obj) ||
Result().template assign<Vertex_const_handle>(&obj)) std::get_if<Vertex_const_handle>(&obj))
return obj; return obj;
const Face_const_handle* p_fh = const auto* p_fh = std::get_if<Face_const_handle>(&obj);
Result().template assign<Face_const_handle>(&obj); // Walk to p from the face we have located:
if (p_fh) if (p_fh) return _walk_from_face(*p_fh, vh->point(), p, crossed_edges);
// Walk to p from the face we have located:
return _walk_from_face(*p_fh, vh->point(), p, crossed_edges);
CGAL_error_msg("_find_face_around_vertex() returned an unknown object."); CGAL_error_msg("_find_face_around_vertex() returned an unknown object.");
} }
@ -185,31 +175,28 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex,
return default_result(); return default_result();
} }
//----------------------------------------------------------------------------- /*! locates an edge around a given vertex that is the predecessor of the curve
// Locate an edge around a given vertex that is the predecessor of the curve * connecting the vertex to the query point in a clockwise order.
// connecting the vertex to the query point in a clockwise order. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
_find_face_around_vertex(Vertex_const_handle vh, _find_face_around_vertex(Vertex_const_handle vh, const Point_2& p,
const Point_2& p, bool& new_vertex) const {
bool& new_vertex) const
{
new_vertex = false; new_vertex = false;
// Create an x-monotone curve connecting the point associated with the // Create an x-monotone curve connecting the point associated with the
// vertex vp and the query point p. // vertex vp and the query point p.
const Point_2& vp = vh->point(); const Point_2& vp = vh->point();
X_monotone_curve_2 seg = X_monotone_curve_2 seg =
m_traits->construct_x_monotone_curve_2_object()(vp, p); m_traits->construct_x_monotone_curve_2_object()(vp, p);
const bool seg_dir_right = const bool seg_dir_right =
(m_traits->compare_xy_2_object()(vp, p) == SMALLER); (m_traits->compare_xy_2_object()(vp, p) == SMALLER);
// Get the first incident halfedge around v and the next halfedge. // Get the first incident halfedge around v and the next halfedge.
Halfedge_around_vertex_const_circulator first = vh->incident_halfedges(); Halfedge_around_vertex_const_circulator first = vh->incident_halfedges();
Halfedge_around_vertex_const_circulator curr, next; Halfedge_around_vertex_const_circulator curr, next;
bool equal_curr = false; bool equal_curr = false;
next = curr = first; next = curr = first;
++next; ++next;
@ -241,16 +228,14 @@ _find_face_around_vertex(Vertex_const_handle vh,
else { else {
// Traverse the halfedges around v until we find the pair of adjacent // Traverse the halfedges around v until we find the pair of adjacent
// halfedges such as seg is located clockwise in between them. // halfedges such as seg is located clockwise in between them.
typename Traits_adaptor_2::Is_between_cw_2 is_between_cw = auto is_between_cw = m_traits->is_between_cw_2_object();
m_traits->is_between_cw_2_object(); bool eq_curr, eq_next;
bool eq_curr, eq_next;
while (! is_between_cw(seg, seg_dir_right, curr->curve(), while (! is_between_cw(seg, seg_dir_right, curr->curve(),
(curr->direction() == ARR_RIGHT_TO_LEFT), (curr->direction() == ARR_RIGHT_TO_LEFT),
next->curve(), next->curve(),
(next->direction() == ARR_RIGHT_TO_LEFT), (next->direction() == ARR_RIGHT_TO_LEFT),
vp, eq_curr, eq_next)) vp, eq_curr, eq_next)) {
{
// Break the loop if seg equals one of the halfedges next to v. // Break the loop if seg equals one of the halfedges next to v.
if (eq_curr) { if (eq_curr) {
equal_curr = true; equal_curr = true;
@ -291,10 +276,9 @@ _find_face_around_vertex(Vertex_const_handle vh,
// Check whether p lies on the curve associated with the edge. // Check whether p lies on the curve associated with the edge.
if (m_traits->is_in_x_range_2_object()(curr->curve(), p) && if (m_traits->is_in_x_range_2_object()(curr->curve(), p) &&
m_traits->compare_y_at_x_2_object()(p, curr->curve()) == EQUAL) m_traits->compare_y_at_x_2_object()(p, curr->curve()) == EQUAL) {
{
// p is located on the interior of the edge. // p is located on the interior of the edge.
Halfedge_const_handle he = curr; Halfedge_const_handle he = curr;
return make_result(he); return make_result(he);
} }
@ -304,22 +288,18 @@ _find_face_around_vertex(Vertex_const_handle vh,
return make_result(curr->source()); return make_result(curr->source());
} }
//----------------------------------------------------------------------------- /*! walks from the edge to the query point.
// Walk from the edge to the query point. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
_walk_from_edge(Halfedge_const_handle eh, _walk_from_edge(Halfedge_const_handle eh, const Point_2& np, const Point_2& p,
const Point_2& np, Halfedge_set& crossed_edges) const {
const Point_2& p,
Halfedge_set& crossed_edges) const
{
CGAL_assertion_msg(! eh->is_fictitious(), CGAL_assertion_msg(! eh->is_fictitious(),
"_walk_from_edge() from a fictitious edge."); "_walk_from_edge() from a fictitious edge.");
const X_monotone_curve_2& cv = eh->curve() ; const X_monotone_curve_2& cv = eh->curve() ;
Comparison_result res; Comparison_result res;
X_monotone_curve_2 seg = X_monotone_curve_2 seg =
m_traits->construct_x_monotone_curve_2_object()(np, p); m_traits->construct_x_monotone_curve_2_object()(np, p);
@ -345,8 +325,7 @@ _walk_from_edge(Halfedge_const_handle eh,
if (m_traits->is_in_x_range_2_object()(seg, temp_p)) { if (m_traits->is_in_x_range_2_object()(seg, temp_p)) {
//we must make sure that eh is not a tip on an "antena" //we must make sure that eh is not a tip on an "antena"
if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL && if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL &&
eh->prev() != eh->twin()) eh->prev() != eh->twin()) {
{
// the assumption is that each edge is crossed at most twice // the assumption is that each edge is crossed at most twice
CGAL_assertion_msg(crossed_edges.count(eh->prev()) < 2, CGAL_assertion_msg(crossed_edges.count(eh->prev()) < 2,
"crossed_edges should contain each halfedge at most twice."); "crossed_edges should contain each halfedge at most twice.");
@ -367,8 +346,7 @@ _walk_from_edge(Halfedge_const_handle eh,
if (m_traits->is_in_x_range_2_object()(seg, temp_p)) { if (m_traits->is_in_x_range_2_object()(seg, temp_p)) {
//we must make sure that eh is not a tip on an "antena" //we must make sure that eh is not a tip on an "antena"
if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL && if (m_traits->compare_y_at_x_2_object()(temp_p, seg) == EQUAL &&
eh->next() != eh->twin()) eh->next() != eh->twin()) {
{
// the assumption is that each edge is crossed at most twice // the assumption is that each edge is crossed at most twice
CGAL_assertion_msg(crossed_edges.count(eh->next()) < 2, CGAL_assertion_msg(crossed_edges.count(eh->next()) < 2,
"crossed_edges should contain each halfedge at most twice."); "crossed_edges should contain each halfedge at most twice.");
@ -428,89 +406,69 @@ _walk_from_edge(Halfedge_const_handle eh,
return (_walk_from_vertex(vh, p, crossed_edges)); return (_walk_from_vertex(vh, p, crossed_edges));
} }
//----------------------------------------------------------------------------- /*! deals with an arrangement curve contained in the segment from the nearest
// In case the arrangement's curve contained in the segment * landmark to the query point
// from the nearest landmark to the query point */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
_deal_with_curve_contained_in_segment(Halfedge_const_handle he, _deal_with_curve_contained_in_segment(Halfedge_const_handle he, bool p_is_left,
bool p_is_left,
const Point_2& p, const Point_2& p,
Halfedge_set& crossed_edges) const Halfedge_set& crossed_edges) const {
{
// in this case we want to walk from to the query point from the nearest // in this case we want to walk from to the query point from the nearest
// vertex either the halfedge's source or target // vertex either the halfedge's source or target
Vertex_const_handle vh; auto cmp_xy = m_traits->compare_xy_2_object();
bool target_is_left; bool target_is_left =
if (m_traits->compare_xy_2_object() (cmp_xy(he->source()->point(), he->target()->point()) == LARGER);
(he->source()->point(),he->target()->point()) == LARGER)
target_is_left = true; Vertex_const_handle vh;
else
target_is_left = false;
if (p_is_left) { if (p_is_left) {
if (target_is_left) if (target_is_left) vh = he->target();
vh = he->target(); else vh = he->source();
else
vh = he->source();
} }
else { else {
if (target_is_left) if (target_is_left) vh = he->source();
vh = he->source(); else vh = he->target();
else
vh = he->target();
} }
// vh is the closest vertex among the halfedge's end points // vh is the closest vertex among the halfedge's end points
return (_walk_from_vertex(vh, p, crossed_edges)); return (_walk_from_vertex(vh, p, crossed_edges));
} }
//----------------------------------------------------------------------------- /*! walks from the given face to the query point.
// Walk from the given face to the query point. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::result_type typename Arr_landmarks_point_location<Arr, Gen>::result_type
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
_walk_from_face(Face_const_handle face, _walk_from_face(Face_const_handle face, const Point_2& np, const Point_2& p,
const Point_2& np, Halfedge_set& crossed_edges) const {
const Point_2& p,
Halfedge_set& crossed_edges) const
{
// Construct an x-monotone curve connecting the nearest landmark point np // Construct an x-monotone curve connecting the nearest landmark point np
// to the query point p and check which CCB intersects this segment. // to the query point p and check which CCB intersects this segment.
X_monotone_curve_2 seg = X_monotone_curve_2 seg =
m_traits->construct_x_monotone_curve_2_object()(np, p); m_traits->construct_x_monotone_curve_2_object()(np, p);
const bool p_is_left = const bool p_is_left = (m_traits->compare_xy_2_object()(np, p) == LARGER);
(m_traits->compare_xy_2_object()(np, p) == LARGER);
Inner_ccb_const_iterator inner_ccb_iter; const Halfedge_const_handle invalid_he;
Outer_ccb_const_iterator outer_ccb_iter; const Vertex_const_handle invalid_vertex;
const Halfedge_const_handle invalid_he; bool cv_is_contained_in_seg;
Halfedge_const_handle he;
Face_const_handle new_face;
bool is_on_edge;
bool is_target;
bool cv_is_contained_in_seg;
Vertex_const_handle new_vertex;
const Vertex_const_handle invalid_vertex;
do { do {
// Check whether p lies inside the current face (including its holes): // Check whether p lies inside the current face (including its holes):
if (p_arr->topology_traits()->is_in_face(&(*face), p, nullptr)) if (p_arr->topology_traits()->is_in_face(&(*face), p, nullptr)) {
{
// We know that p is located inside the current face, and we check // We know that p is located inside the current face, and we check
// whether it lies inside one of its holes (or on the boundary of // whether it lies inside one of its holes (or on the boundary of
// its holes). // its holes).
cv_is_contained_in_seg = false; cv_is_contained_in_seg = false;
new_face = face; auto new_face = face;
for (inner_ccb_iter = face->inner_ccbs_begin(); for (auto inner_ccb_iter = face->inner_ccbs_begin();
inner_ccb_iter != face->inner_ccbs_end(); ++inner_ccb_iter) inner_ccb_iter != face->inner_ccbs_end(); ++inner_ccb_iter) {
{ bool is_on_edge;
he = _intersection_with_ccb(*inner_ccb_iter,seg, p, p_is_left, bool is_target;
crossed_edges,is_on_edge, is_target, Vertex_const_handle new_vertex;
cv_is_contained_in_seg,new_vertex); Halfedge_const_handle he =
if (he == invalid_he && cv_is_contained_in_seg) _intersection_with_ccb(*inner_ccb_iter,seg, p, p_is_left,
{ crossed_edges, is_on_edge, is_target,
cv_is_contained_in_seg, new_vertex);
if (he == invalid_he && cv_is_contained_in_seg) {
return _deal_with_curve_contained_in_segment(*inner_ccb_iter, return _deal_with_curve_contained_in_segment(*inner_ccb_iter,
p_is_left,p, p_is_left,p,
crossed_edges); crossed_edges);
@ -535,8 +493,7 @@ _walk_from_face(Face_const_handle face,
// Check if we found a new face (hole) containing p. If not, the current // Check if we found a new face (hole) containing p. If not, the current
// face contains p. // face contains p.
if (new_face == face) if (new_face == face) return make_result(face);
return make_result(face);
// Continue from the new face (hole). // Continue from the new face (hole).
face = new_face; face = new_face;
@ -544,13 +501,16 @@ _walk_from_face(Face_const_handle face,
else { else {
// We know that p is not located inside the current face. We therefore // We know that p is not located inside the current face. We therefore
// look for an edge on its outer boundary that intersects seg. // look for an edge on its outer boundary that intersects seg.
new_face = face; auto new_face = face;
for (outer_ccb_iter = face->outer_ccbs_begin(); for (auto outer_ccb_iter = face->outer_ccbs_begin();
outer_ccb_iter != face->outer_ccbs_end(); ++outer_ccb_iter) outer_ccb_iter != face->outer_ccbs_end(); ++outer_ccb_iter) {
{ bool is_on_edge;
he = _intersection_with_ccb(*outer_ccb_iter,seg, p, p_is_left, bool is_target;
crossed_edges,is_on_edge, is_target, Vertex_const_handle new_vertex;
cv_is_contained_in_seg,new_vertex); Halfedge_const_handle he =
_intersection_with_ccb(*outer_ccb_iter,seg, p, p_is_left,
crossed_edges, is_on_edge, is_target,
cv_is_contained_in_seg, new_vertex);
if (he == invalid_he && cv_is_contained_in_seg) { if (he == invalid_he && cv_is_contained_in_seg) {
return _deal_with_curve_contained_in_segment(*outer_ccb_iter, return _deal_with_curve_contained_in_segment(*outer_ccb_iter,
p_is_left,p, p_is_left,p,
@ -585,10 +545,9 @@ _walk_from_face(Face_const_handle face,
return default_result(); return default_result();
} }
//----------------------------------------------------------------------------- /*! finds a halfedge on the given CCB that intersects the given x-monotone
// Find a halfedge on the given CCB that intersects the given x-monotone * curve, connecting the current landmark to the query point.
// curve, connecting the current landmark to the query point. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
typename Arr_landmarks_point_location<Arr, Gen>::Halfedge_const_handle typename Arr_landmarks_point_location<Arr, Gen>::Halfedge_const_handle
Arr_landmarks_point_location<Arr, Gen>:: Arr_landmarks_point_location<Arr, Gen>::
@ -598,17 +557,15 @@ _intersection_with_ccb(Ccb_halfedge_const_circulator circ,
Halfedge_set& crossed_edges, Halfedge_set& crossed_edges,
bool& is_on_edge, bool& is_target, bool& is_on_edge, bool& is_target,
bool& cv_is_contained_in_seg, bool& cv_is_contained_in_seg,
Vertex_const_handle & new_vertex) const Vertex_const_handle& new_vertex) const {
{
is_on_edge = false; is_on_edge = false;
is_target = false; is_target = false;
// Go over the CCB. // Go over the CCB.
typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range = auto is_in_x_range = m_traits->is_in_x_range_2_object();
m_traits->is_in_x_range_2_object(); Ccb_halfedge_const_circulator curr = circ , temp_circ;
Ccb_halfedge_const_circulator curr = circ , temp_circ; const Halfedge_const_handle invalid_he;
const Halfedge_const_handle invalid_he; Halfedge_const_handle he;
Halfedge_const_handle he;
bool cv_and_seg_overlap; bool cv_and_seg_overlap;
do { do {
he = curr; he = curr;
@ -646,33 +603,28 @@ _intersection_with_ccb(Ccb_halfedge_const_circulator circ,
// Check whether the current curve intersects seg an odd number of times. // Check whether the current curve intersects seg an odd number of times.
if (_have_odd_intersections(he->curve(), seg, p_is_left, if (_have_odd_intersections(he->curve(), seg, p_is_left,
is_on_edge,cv_and_seg_overlap, is_on_edge,cv_and_seg_overlap,
cv_is_contained_in_seg) cv_is_contained_in_seg) &&
&& !(cv_and_seg_overlap || cv_is_contained_in_seg)) ! (cv_and_seg_overlap || cv_is_contained_in_seg)) {
{
// Check if the query point lies on the current edge, or whether // Check if the query point lies on the current edge, or whether
// it lies in its interior. // it lies in its interior.
if (is_on_edge) if (is_on_edge)
return _in_case_p_is_on_edge(he,crossed_edges,p,is_target); return _in_case_p_is_on_edge(he,crossed_edges,p,is_target);
if ((!curr->target()->is_at_open_boundary()) && if ((!curr->target()->is_at_open_boundary()) &&
is_in_x_range(seg, curr->target()->point())) is_in_x_range(seg, curr->target()->point())) {
{
// if the target point of curr is located on seg // if the target point of curr is located on seg
// we should walk from it to the query point // we should walk from it to the query point
if (m_traits->compare_y_at_x_2_object() if (m_traits->compare_y_at_x_2_object()
(curr->target()->point(), seg) == EQUAL) (curr->target()->point(), seg) == EQUAL) {
{
new_vertex = curr->target(); new_vertex = curr->target();
} }
} }
else if ((!curr->source()->is_at_open_boundary()) && else if ((!curr->source()->is_at_open_boundary()) &&
is_in_x_range(seg , curr->source()->point() )) is_in_x_range(seg , curr->source()->point())) {
{
// if the source point of curr is located on seg // if the source point of curr is located on seg
// we should walk from it to the query point // we should walk from it to the query point
if (m_traits->compare_y_at_x_2_object() if (m_traits->compare_y_at_x_2_object()
(curr->source()->point() , seg) == EQUAL) (curr->source()->point(), seg) == EQUAL) {
{
new_vertex = curr->source(); new_vertex = curr->source();
} }
} }
@ -718,8 +670,7 @@ Arr_landmarks_point_location<Arr, Gen>::
_in_case_p_is_on_edge(Halfedge_const_handle he, _in_case_p_is_on_edge(Halfedge_const_handle he,
Halfedge_set& crossed_edges, Halfedge_set& crossed_edges,
const Point_2 & p, const Point_2 & p,
bool & is_target) const bool & is_target) const {
{
// cv and seg overlap, obviously we crossed it // cv and seg overlap, obviously we crossed it
// the assumption is that each edge is crossed at most twice // the assumption is that each edge is crossed at most twice
CGAL_assertion_msg(crossed_edges.count(he) < 2, CGAL_assertion_msg(crossed_edges.count(he) < 2,
@ -728,14 +679,12 @@ _in_case_p_is_on_edge(Halfedge_const_handle he,
crossed_edges.insert(he->twin()); crossed_edges.insert(he->twin());
// Check if p equals one of the edge end-vertices. // Check if p equals one of the edge end-vertices.
if (! he->target()->is_at_open_boundary() && if (! he->target()->is_at_open_boundary() &&
m_traits->compare_xy_2_object()(he->target()->point(), p) == EQUAL) m_traits->compare_xy_2_object()(he->target()->point(), p) == EQUAL) {
{
// p is the target of the current halfedge. // p is the target of the current halfedge.
is_target = true; is_target = true;
} }
else if (! he->source()->is_at_open_boundary() && else if (! he->source()->is_at_open_boundary() &&
m_traits->compare_xy_2_object()(he->source()->point(), p) == EQUAL) m_traits->compare_xy_2_object()(he->source()->point(), p) == EQUAL) {
{
// Take the twin halfedge, so p equals its target. // Take the twin halfedge, so p equals its target.
he = he->twin(); he = he->twin();
is_target = true; is_target = true;
@ -744,21 +693,17 @@ _in_case_p_is_on_edge(Halfedge_const_handle he,
return he; return he;
} }
//----------------------------------------------------------------------------- /*! checks whether the given curve intersects a simple segment, which connects
// Check whether the given curve intersects a simple segment, which connects * the current landmark to the query point, an odd number of times.
// the current landmark to the query point, an odd number of times. */
//
template <typename Arr, typename Gen> template <typename Arr, typename Gen>
bool Arr_landmarks_point_location<Arr, Gen>:: bool Arr_landmarks_point_location<Arr, Gen>::
_have_odd_intersections(const X_monotone_curve_2& cv, _have_odd_intersections(const X_monotone_curve_2& cv,
const X_monotone_curve_2& seg, const X_monotone_curve_2& seg,
bool p_is_left, bool p_is_left, bool& p_on_curve,
bool& p_on_curve,
bool& cv_and_seg_overlap, bool& cv_and_seg_overlap,
bool& cv_is_contained_in_seg) const bool& cv_is_contained_in_seg) const {
{ auto is_in_x_range = m_traits->is_in_x_range_2_object();
typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range =
m_traits->is_in_x_range_2_object();
p_on_curve = false; p_on_curve = false;
cv_and_seg_overlap = false; cv_and_seg_overlap = false;
cv_is_contained_in_seg = false; cv_is_contained_in_seg = false;
@ -776,9 +721,9 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
cv_right = m_traits->construct_max_vertex_2_object()(cv); cv_right = m_traits->construct_max_vertex_2_object()(cv);
if (cv_left_is_closed && cv_right_is_closed) { if (cv_left_is_closed && cv_right_is_closed) {
if (is_in_x_range(seg,cv_left) && is_in_x_range(seg,cv_right)) { if (is_in_x_range(seg,cv_left) && is_in_x_range(seg,cv_right)) {
if ((m_traits->compare_y_at_x_2_object()(cv_left, seg) == EQUAL) && auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
(m_traits->compare_y_at_x_2_object()(cv_right, seg) == EQUAL)) if ((cmp_y_at_x(cv_left, seg) == EQUAL) &&
{ (cmp_y_at_x(cv_right, seg) == EQUAL)) {
// cv is contained in seg non of the answer true or false is correct // cv is contained in seg non of the answer true or false is correct
// we must set a special flag to distinguish this case // we must set a special flag to distinguish this case
cv_is_contained_in_seg = true; cv_is_contained_in_seg = true;
@ -792,21 +737,18 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// Check if the left endpoint of cv has the same x-coordinate as the // Check if the left endpoint of cv has the same x-coordinate as the
// right endpoint of seg. // right endpoint of seg.
if (m_traits->compare_x_2_object() if (m_traits->compare_x_2_object()
(m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL) (m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL) {
{
if (! p_is_left && if (! p_is_left &&
m_traits->compare_xy_2_object() m_traits->compare_xy_2_object()
(m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL) (m_traits->construct_min_vertex_2_object()(cv), seg_right) == EQUAL) {
{
p_on_curve = true; p_on_curve = true;
return true; return true;
} }
else if (m_traits->is_vertical_2_object()(seg)) { else if (m_traits->is_vertical_2_object()(seg)) {
auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
// Special treatment for vertical segments. // Special treatment for vertical segments.
Comparison_result res_l = Comparison_result res_l = cmp_y_at_x(seg_left, cv);
m_traits->compare_y_at_x_2_object()(seg_left, cv); Comparison_result res_r = cmp_y_at_x(seg_right, cv);
Comparison_result res_r =
m_traits->compare_y_at_x_2_object()(seg_right, cv);
if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) { if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) {
p_on_curve = true; p_on_curve = true;
return true; return true;
@ -820,22 +762,18 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// Check if the right endpoint of cv has the same x-coordinate as the // Check if the right endpoint of cv has the same x-coordinate as the
// left endpoint of seg. // left endpoint of seg.
if (m_traits->compare_x_2_object() if (m_traits->compare_x_2_object()
(m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL) (m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL) {
{
if (p_is_left && if (p_is_left &&
m_traits->compare_xy_2_object() m_traits->compare_xy_2_object()
(m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL) (m_traits->construct_max_vertex_2_object()(cv), seg_left) == EQUAL) {
{
p_on_curve = true; p_on_curve = true;
return true; return true;
} }
else if (m_traits->is_vertical_2_object()(seg)) { else if (m_traits->is_vertical_2_object()(seg)) {
// Special treatment for vertical segments. // Special treatment for vertical segments.
Comparison_result res_l = auto cmp_y_at_x = m_traits->compare_y_at_x_2_object();
m_traits->compare_y_at_x_2_object()(seg_left, cv); Comparison_result res_l = cmp_y_at_x(seg_left, cv);
Comparison_result res_r = Comparison_result res_r = cmp_y_at_x(seg_right, cv);
m_traits->compare_y_at_x_2_object()(seg_right, cv);
if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) { if ((p_is_left && res_l == EQUAL) || (! p_is_left && res_r == EQUAL)) {
p_on_curve = true; p_on_curve = true;
return true; return true;
@ -846,8 +784,8 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
} }
} }
// Compare the two left ends of cv and seg. // Compare the two left ends of cv and seg.
Comparison_result left_res; Comparison_result left_res;
const Arr_parameter_space bx_l = const Arr_parameter_space bx_l =
m_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); m_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END);
if (bx_l == ARR_LEFT_BOUNDARY) { if (bx_l == ARR_LEFT_BOUNDARY) {
// The left end of cv lies to the left of seg_left: // The left end of cv lies to the left of seg_left:
@ -858,11 +796,11 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// The left end of cv lies to the right of seg_left. // The left end of cv lies to the right of seg_left.
// Compare the left endpoint of cv to seg. // Compare the left endpoint of cv to seg.
left_res = m_traits->compare_y_at_x_2_object() left_res = m_traits->compare_y_at_x_2_object()
(m_traits->construct_min_vertex_2_object()(cv), seg); (m_traits->construct_min_vertex_2_object()(cv), seg);
left_res = CGAL::opposite(left_res); left_res = CGAL::opposite(left_res);
} }
else { else {
const Arr_parameter_space by_l = const Arr_parameter_space by_l =
m_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); m_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END);
if (by_l == ARR_BOTTOM_BOUNDARY) if (by_l == ARR_BOTTOM_BOUNDARY)
// The left end of cv is at y = -oo, so cv obviously lies above it. // The left end of cv is at y = -oo, so cv obviously lies above it.
@ -876,8 +814,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
Comparison_result res = m_traits->compare_xy_2_object()(cv_left, seg_left); Comparison_result res = m_traits->compare_xy_2_object()(cv_left, seg_left);
if (res != LARGER) { if (res != LARGER) {
left_res = m_traits->compare_y_at_x_2_object()(seg_left, cv); left_res = m_traits->compare_y_at_x_2_object()(seg_left, cv);
if (p_is_left && left_res == EQUAL) if (p_is_left && left_res == EQUAL) {
{
// In this case the query point p, which is the left endpoint of seg, // In this case the query point p, which is the left endpoint of seg,
// lies on cv. // lies on cv.
p_on_curve = true; p_on_curve = true;
@ -904,8 +841,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// we must set a special flag to distinguish this case // we must set a special flag to distinguish this case
if (is_in_x_range(cv,( p_is_left ? seg_left : seg_right))) if (is_in_x_range(cv,( p_is_left ? seg_left : seg_right)))
if (m_traits->compare_y_at_x_2_object() if (m_traits->compare_y_at_x_2_object()
((p_is_left ? seg_left : seg_right), cv) == EQUAL) ((p_is_left ? seg_left : seg_right), cv) == EQUAL) {
{
p_on_curve = true; p_on_curve = true;
} }
cv_and_seg_overlap = true; cv_and_seg_overlap = true;
@ -913,8 +849,8 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
} }
} }
// Compare the two right ends of cv and seg. // Compare the two right ends of cv and seg.
Comparison_result right_res; Comparison_result right_res;
const Arr_parameter_space bx_r = const Arr_parameter_space bx_r =
m_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); m_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END);
if (bx_r == ARR_RIGHT_BOUNDARY) { if (bx_r == ARR_RIGHT_BOUNDARY) {
// The right end of cv lies to the right of seg_right: // The right end of cv lies to the right of seg_right:
@ -925,11 +861,11 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// The right end of cv lies to the left of seg_right. // The right end of cv lies to the left of seg_right.
// Compare the right endpoint of cv to seg. // Compare the right endpoint of cv to seg.
right_res = m_traits->compare_y_at_x_2_object() right_res = m_traits->compare_y_at_x_2_object()
(m_traits->construct_max_vertex_2_object()(cv), seg); (m_traits->construct_max_vertex_2_object()(cv), seg);
right_res = CGAL::opposite(right_res); right_res = CGAL::opposite(right_res);
} }
else { else {
const Arr_parameter_space by_r = const Arr_parameter_space by_r =
m_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); m_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END);
if (by_r == ARR_BOTTOM_BOUNDARY) if (by_r == ARR_BOTTOM_BOUNDARY)
// The right end of cv is at y = -oo, so cv obviously lies above it. // The right end of cv is at y = -oo, so cv obviously lies above it.
@ -972,8 +908,7 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
// we must set a special flag to distinguish this case // we must set a special flag to distinguish this case
if (is_in_x_range(cv, (p_is_left ? seg_left : seg_right))) if (is_in_x_range(cv, (p_is_left ? seg_left : seg_right)))
if (m_traits->compare_y_at_x_2_object() if (m_traits->compare_y_at_x_2_object()
((p_is_left ? seg_left : seg_right), cv) == EQUAL) ((p_is_left ? seg_left : seg_right), cv) == EQUAL) {
{
p_on_curve = true; p_on_curve = true;
} }
cv_and_seg_overlap = true; cv_and_seg_overlap = true;
@ -986,6 +921,6 @@ _have_odd_intersections(const X_monotone_curve_2& cv,
return (left_res != right_res); return (left_res != right_res);
} }
} //namespace CGAL } // namespace CGAL
#endif #endif