Skip to content

Commit

Permalink
Cleaned up and dispatched is_intersection_valid_impl() properly
Browse files Browse the repository at this point in the history
  • Loading branch information
efifogel committed Aug 9, 2023
1 parent afa58a9 commit ada39fd
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,46 @@ template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& /* intersection_location */,
Arr_all_sides_oblivious_tag) const
Arr_boundary_cond_tag) const
{ return (m_geom_traits->compare_xy_2_object()(ip, m_left_pt) == LARGER); }

template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& intersection_location,
Arr_not_all_sides_oblivious_tag) const {
Arr_has_identified_side_tag) const {
auto equal = m_geom_traits->equal_2_object();
auto is_on_y_ident = m_geom_traits->is_on_y_identification_2_object();
// Case 1: the curve lies on the y-identification
if (is_on_y_ident(m_cv)) {
if (equal(ip, m_left_pt)) return false;
// We set the location to be on the left as a convention
intersection_location = ARR_LEFT_BOUNDARY;
return true;
}

// Case 2: The left-end lies on the left boundary
// (It cannot lie on the right boundary)
// If the intersection point is not equal to the left-end, it must lie to
// its right; thus valid.
if (m_left_on_boundary) return ! equal(ip, m_left_pt);

// Case 3: The right-end lies on the right boundary
if (m_right_on_boundary && equal(ip, m_right_pt)) {
intersection_location = ARR_RIGHT_BOUNDARY;
return true;
}

// We have a simple intersection point;
// make sure it lies to the right of m_left_pt.
return (m_geom_traits->compare_xy_2_object()(ip, m_left_pt) == LARGER);
}

template <typename Arrangement, typename ZoneVisitor>
bool Arrangement_zone_2<Arrangement, ZoneVisitor>::
is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& intersection_location,
Arr_has_open_side_tag) const {
auto equal = m_geom_traits->equal_2_object();
if (m_left_on_boundary) {
// The left-end lies on the left boundary. If the intersection point is not
Expand Down Expand Up @@ -699,12 +731,12 @@ _is_to_left_impl(const Point_2& p, Halfedge_handle he,
if (ps_x_min == ARR_LEFT_BOUNDARY) return false;

auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y = ps_in_y(he->curve(), ARR_MIN_END);
if (ps_y != ARR_INTERIOR) {
auto ps_y_min = ps_in_y(he->curve(), ARR_MIN_END);
if (ps_y_min != ARR_INTERIOR) {
// Check if p is to the left of the minimal curve-end:
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
const auto res = cmp_x(p, he->curve(), ARR_MIN_END);
return ((res == SMALLER) || (res == EQUAL && ps_y == ARR_TOP_BOUNDARY));
return ((res == SMALLER) || (res == EQUAL && ps_y_min == ARR_TOP_BOUNDARY));
}

// In case the minimal curve-end does not have boundary conditions, simply
Expand Down Expand Up @@ -738,12 +770,12 @@ _is_to_right_impl(const Point_2& p, Halfedge_handle he,
if (ps_x_max == ARR_LEFT_BOUNDARY) return true;

auto ps_in_y = m_geom_traits->parameter_space_in_y_2_object();
auto ps_y = ps_in_y(he->curve(), ARR_MAX_END);
if (ps_y != ARR_INTERIOR) {
auto ps_y_max = ps_in_y(he->curve(), ARR_MAX_END);
if (ps_y_max != ARR_INTERIOR) {
// Check if p is to the right of the maximal curve-end:
auto cmp_x = m_geom_traits->compare_x_point_curve_end_2_object();
auto res = cmp_x(p, he->curve(), ARR_MAX_END);
return ((res == LARGER) || (res == EQUAL && ps_y == ARR_BOTTOM_BOUNDARY));
return ((res == LARGER) || (res == EQUAL && ps_y_max == ARR_BOTTOM_BOUNDARY));
}

// In case the maximal curve-end does not have boundary conditions, simply
Expand Down Expand Up @@ -783,7 +815,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary,
// entirely to the right of m_intersect_p, its intersection with m_cv (if any)
// cannot lie to the left of this point. We therefore do not need to compute
// this intersection.
if (m_found_intersect && (leftmost_location != ARR_RIGHT_BOUNDARY) &&
if (m_found_intersect && (leftmost_location == ARR_INTERIOR) &&
_is_to_left(m_intersect_p, he_curr))
return;

Expand Down
104 changes: 55 additions & 49 deletions Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,65 +55,70 @@ namespace CGAL {
template <typename Arrangement_, typename ZoneVisitor_>
class Arrangement_zone_2 {
public:
typedef Arrangement_ Arrangement_2;
typedef typename Arrangement_2::Geometry_traits_2 Geometry_traits_2;
typedef typename Arrangement_2::Topology_traits Topology_traits;
using Arrangement_2 = Arrangement_;
using Geometry_traits_2 = typename Arrangement_2::Geometry_traits_2;
using Topology_traits = typename Arrangement_2::Topology_traits;

protected:
typedef Arr_traits_adaptor_2<Geometry_traits_2> Traits_adaptor_2;
using Traits_adaptor_2 = Arr_traits_adaptor_2<Geometry_traits_2>;

typedef typename Traits_adaptor_2::Left_side_category Left_side_category;
typedef typename Traits_adaptor_2::Bottom_side_category Bottom_side_category;
typedef typename Traits_adaptor_2::Top_side_category Top_side_category;
typedef typename Traits_adaptor_2::Right_side_category Right_side_category;
using Left_side_category = typename Traits_adaptor_2::Left_side_category;
using Bottom_side_category = typename Traits_adaptor_2::Bottom_side_category;
using Top_side_category = typename Traits_adaptor_2::Top_side_category;
using Right_side_category = typename Traits_adaptor_2::Right_side_category;

static_assert(Arr_sane_identified_tagging<Left_side_category,
Bottom_side_category,
Bottom_side_category,
Top_side_category,
Right_side_category>::value);
// Categories for dispatching
using Are_all_sides_oblivious_category =
typename Arr_all_sides_oblivious_category<Left_side_category,
Bottom_side_category,
Top_side_category,
Right_side_category>::result;

using Left_or_right_sides_category =
typename Arr_two_sides_category<Left_side_category,
Right_side_category>::result;

public:
typedef ZoneVisitor_ Visitor;
using Visitor = ZoneVisitor_;

typedef typename Arrangement_2::Vertex_handle Vertex_handle;
typedef typename Arrangement_2::Halfedge_handle Halfedge_handle;
typedef typename Arrangement_2::Face_handle Face_handle;
using Vertex_handle = typename Arrangement_2::Vertex_handle;
using Halfedge_handle = typename Arrangement_2::Halfedge_handle;
using Face_handle = typename Arrangement_2::Face_handle;

typedef std::pair<Halfedge_handle, bool> Visitor_result;
using Visitor_result = std::pair<Halfedge_handle, bool>;

typedef typename Geometry_traits_2::Point_2 Point_2;
typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef typename Geometry_traits_2::Multiplicity Multiplicity;
using Point_2 = typename Geometry_traits_2::Point_2;
using X_monotone_curve_2 = typename Geometry_traits_2::X_monotone_curve_2;
using Multiplicity = typename Geometry_traits_2::Multiplicity;

protected:
typedef typename Arr_all_sides_oblivious_category<Left_side_category,
Bottom_side_category,
Top_side_category,
Right_side_category>::result
Are_all_sides_oblivious_category;

typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
// General types
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
using Face_const_handle = typename Arrangement_2::Face_const_handle;

typedef typename Arrangement_2::Ccb_halfedge_circulator
Ccb_halfedge_circulator;
using Ccb_halfedge_circulator =
typename Arrangement_2::Ccb_halfedge_circulator;

// Types used for caching intersection points:
typedef std::pair<Point_2, Multiplicity> Intersection_point;
typedef boost::variant<Intersection_point, X_monotone_curve_2>
Intersection_result;
typedef boost::optional<Intersection_result> Optional_intersection;
typedef std::list<Intersection_result> Intersect_list;
typedef std::map<const X_monotone_curve_2*, Intersect_list>
Intersect_map;
typedef typename Intersect_map::iterator Intersect_map_iterator;
using Intersection_point = std::pair<Point_2, Multiplicity>;
using Intersection_result =
boost::variant<Intersection_point, X_monotone_curve_2>;
using Optional_intersection = boost::optional<Intersection_result>;
using Intersect_list = std::list<Intersection_result>;
using Intersect_map =
std::map<const X_monotone_curve_2*, Intersect_list>;
using Intersect_map_iterator = typename Intersect_map::iterator;

typedef std::set<const X_monotone_curve_2*> Curves_set;
typedef typename Curves_set::iterator Curves_set_iterator;
using Curves_set = std::set<const X_monotone_curve_2*>;
using Curves_set_iterator = typename Curves_set::iterator;

typedef Arr_point_location_result<Arrangement_2> Pl_result;
typedef typename Pl_result::Type Pl_result_type;
using Pl_result = Arr_point_location_result<Arrangement_2>;
using Pl_result_type = typename Pl_result::Type;

// Data members:
Arrangement_2& m_arr; // The associated arrangement.
Expand Down Expand Up @@ -193,8 +198,7 @@ class Arrangement_zone_2 {
* \param pl A point-location object associated with the arrangement.
*/
template <typename PointLocation>
void init(const X_monotone_curve_2& cv, const PointLocation& pl)
{
void init(const X_monotone_curve_2& cv, const PointLocation& pl) {
// Set the curve and check whether its left end has boundary conditions.
m_cv = cv;

Expand Down Expand Up @@ -267,8 +271,7 @@ class Arrangement_zone_2 {
*/
bool do_overlap_impl(const X_monotone_curve_2& cv1,
const X_monotone_curve_2& cv2,
const Point_2& p, Arr_all_sides_oblivious_tag) const
{
const Point_2& p, Arr_all_sides_oblivious_tag) const {
return m_geom_traits->compare_y_at_x_right_2_object()(cv1, cv2, p) == EQUAL;
}

Expand Down Expand Up @@ -381,8 +384,7 @@ class Arrangement_zone_2 {
{ return (_is_to_right_impl(p, he, Are_all_sides_oblivious_category())); }

bool _is_to_right_impl(const Point_2& p, Halfedge_handle he,
Arr_all_sides_oblivious_tag) const
{
Arr_all_sides_oblivious_tag) const {
return (((he->direction() == ARR_LEFT_TO_RIGHT) &&
m_geom_traits->compare_xy_2_object()(p, he->target()->point()) ==
LARGER) ||
Expand All @@ -400,16 +402,20 @@ class Arrangement_zone_2 {
bool is_intersection_valid(const Point_2& ip,
Arr_parameter_space& intersection_location) const {
return is_intersection_valid_impl(ip, intersection_location,
Are_all_sides_oblivious_category());
Left_or_right_sides_category());
}

bool is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& intersection_location,
Arr_all_sides_oblivious_tag) const;
Arr_boundary_cond_tag) const;

bool is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& intersection_location,
Arr_has_identified_side_tag) const;

bool is_intersection_valid_impl(const Point_2& ip,
Arr_parameter_space& intersection_location,
Arr_not_all_sides_oblivious_tag) const;
Arr_has_open_side_tag) const;

/*! Compute the (lexicographically) leftmost intersection of the query
* curve with a given halfedge on the boundary of a face in the arrangement.
Expand Down

0 comments on commit ada39fd

Please sign in to comment.