[get_turns] Use RobustPolicy in a unified way in all three get_turn_info* policies (A/A, L/A, and L/L).

Newly introduced intersection_info containing IntersectionResult, SideCalculator and Point refs is used also in get_turn_info for A/A.
Robust points are stored only if RobustPolicy is not no_rescale_policy.
This commit also fixes an error in get_turn_info - swapped_side_calc created for method_touch_interior ('m') should use robust points just like the original one.
This commit is contained in:
Adam Wulkiewicz
2014-05-04 01:26:12 +02:00
parent bff1c65b0a
commit e6ef0b0328
5 changed files with 447 additions and 284 deletions

View File

@@ -21,7 +21,7 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/policies/robustness/robust_point_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
@@ -60,36 +60,6 @@ public:
namespace detail { namespace overlay
{
template <typename PointP, typename PointQ,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
struct side_calculator
{
typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
Qi const& qi, Qj const& qj, Qk const& qk)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); }
inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); }
inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); }
inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); }
inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }
inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }
Pi const& m_pi;
Pj const& m_pj;
Pk const& m_pk;
Qi const& m_qi;
Qj const& m_qj;
Qk const& m_qk;
};
struct base_turn_handler
{
// Returns true if both sides are opposite
@@ -947,41 +917,12 @@ struct get_turn_info
RobustPolicy const& robust_policy,
OutputIterator out)
{
typedef typename geometry::robust_point_type
<
Point1, RobustPolicy
>::type robust_point_type;
typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters_info;
robust_point_type pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob;
geometry::recalculate(pi_rob, pi, robust_policy);
geometry::recalculate(pj_rob, pj, robust_policy);
geometry::recalculate(pk_rob, pk, robust_policy);
geometry::recalculate(qi_rob, qi, robust_policy);
geometry::recalculate(qj_rob, qj, robust_policy);
geometry::recalculate(qk_rob, qk, robust_policy);
inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj);
segment_type2 q1(qi, qj);
side_calculator<robust_point_type, robust_point_type> side_calc(pi_rob, pj_rob, pk_rob, qi_rob, qj_rob, qk_rob);
typedef strategy_intersection
<
typename cs_tag<typename TurnInfo::point_type>::type,
Point1,
Point2,
typename TurnInfo::point_type,
RobustPolicy
> si;
typedef typename si::segment_intersection_strategy_type strategy;
typename strategy::return_type result = strategy::apply(p1, q1,
robust_policy, pi_rob, pj_rob, qi_rob, qj_rob);
char const method = result.template get<1>().how;
char const method = inters.d_info().how;
// Copy, to copy possibly extended fields
TurnInfo tp = tp_model;
@@ -993,11 +934,10 @@ struct get_turn_info
case 'f' : // collinear, "from"
case 's' : // starts from the middle
if (AssignPolicy::include_no_turn
&& result.template get<0>().count > 0)
&& inters.i_info().count > 0)
{
only_convert::apply(tp,
result.template get<0>());
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
only_convert::apply(tp, inters.i_info());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
break;
@@ -1013,29 +953,34 @@ struct get_turn_info
> policy;
// If Q (1) arrives (1)
if (result.template get<1>().arrival[1] == 1)
if ( inters.d_info().arrival[1] == 1 )
{
policy::template apply<0>(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(),
side_calc);
tp, inters.i_info(), inters.d_info(),
inters.sides());
}
else
{
// Swap p/q
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
side_calculator
<
typename inters_info::robust_point2_type,
typename inters_info::robust_point1_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
inters.rpi(), inters.rpj(), inters.rpk());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, result.template get<0>(), result.template get<1>(),
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
}
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
break;
case 'i' :
{
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
tp, inters.i_info(), inters.d_info());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
break;
@@ -1043,20 +988,20 @@ struct get_turn_info
{
// Both touch (both arrive there)
touch<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
tp, inters.i_info(), inters.d_info(), inters.sides());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
break;
case 'e':
{
if (! result.template get<1>().opposite)
if ( ! inters.d_info().opposite )
{
// Both equal
// or collinear-and-ending at intersection point
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
tp, inters.i_info(), inters.d_info(), inters.sides());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
else
@@ -1066,21 +1011,21 @@ struct get_turn_info
TurnInfo,
AssignPolicy
>::apply(pi, qi,
tp, out, result.template get<0>(), result.template get<1>());
tp, out, inters.i_info(), inters.d_info());
}
}
break;
case 'c' :
{
// Collinear
if (! result.template get<1>().opposite)
if ( ! inters.d_info().opposite )
{
if (result.template get<1>().arrival[0] == 0)
if ( inters.d_info().arrival[0] == 0 )
{
// Collinear, but similar thus handled as equal
equal<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
tp, inters.i_info(), inters.d_info(), inters.sides());
// override assigned method
tp.method = method_collinear;
@@ -1088,10 +1033,10 @@ struct get_turn_info
else
{
collinear<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>(), side_calc);
tp, inters.i_info(), inters.d_info(), inters.sides());
}
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
else
@@ -1101,7 +1046,7 @@ struct get_turn_info
TurnInfo,
AssignPolicy
>::apply(pi, pj, pk, qi, qj, qk,
tp, out, result.template get<0>(), result.template get<1>(), side_calc);
tp, out, inters.i_info(), inters.d_info(), inters.sides());
}
}
break;
@@ -1110,8 +1055,8 @@ struct get_turn_info
// degenerate points
if (AssignPolicy::include_degenerate)
{
only_convert::apply(tp, result.template get<0>());
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
only_convert::apply(tp, inters.i_info());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
}

View File

@@ -15,177 +15,13 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_FOR_ENDPOINT_HPP
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay {
// TURN_OPERATION
enum turn_position { position_middle, position_front, position_back };
template <typename SegmentRatio>
struct turn_operation_linear
: public turn_operation<SegmentRatio>
{
turn_operation_linear()
: position(position_middle)
, is_collinear(false)
{}
turn_position position;
bool is_collinear; // valid only for Linear geometry
};
template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
class intersection_info
{
typedef typename strategy_intersection
<
typename cs_tag<TurnPoint>::type,
Point1,
Point2,
TurnPoint,
RobustPolicy
>::segment_intersection_strategy_type strategy;
public:
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
typedef side_calculator<Point1, Point2> side_calculator_type;
typedef typename strategy::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
: m_result(strategy::apply(segment_type1(pi, pj),
segment_type2(qi, qj),
robust_policy))
, m_side_calc(pi, pj, pk, qi, qj, qk)
, m_robust_policy(robust_policy)
{}
inline Point1 const& pi() const { return m_side_calc.m_pi; }
inline Point1 const& pj() const { return m_side_calc.m_pj; }
inline Point1 const& pk() const { return m_side_calc.m_pk; }
inline Point2 const& qi() const { return m_side_calc.m_qi; }
inline Point2 const& qj() const { return m_side_calc.m_qj; }
inline Point2 const& qk() const { return m_side_calc.m_qk; }
inline side_calculator_type const& sides() const { return m_side_calc; }
inline result_type const& result() const { return m_result; }
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
// TODO: not it's more like is_spike_ip_p
inline bool is_spike_p() const
{
if ( m_side_calc.pk_wrt_p1() == 0 )
{
if ( ! is_ip_j<0>() )
return false;
int const qk_p1 = m_side_calc.qk_wrt_p1();
int const qk_p2 = m_side_calc.qk_wrt_p2();
if ( qk_p1 == -qk_p2 )
{
if ( qk_p1 == 0 )
{
return is_spike_of_collinear(pi(), pj(), pk());
}
return true;
}
}
return false;
}
// TODO: not it's more like is_spike_ip_q
inline bool is_spike_q() const
{
if ( m_side_calc.qk_wrt_q1() == 0 )
{
if ( ! is_ip_j<1>() )
return false;
int const pk_q1 = m_side_calc.pk_wrt_q1();
int const pk_q2 = m_side_calc.pk_wrt_q2();
if ( pk_q1 == -pk_q2 )
{
if ( pk_q1 == 0 )
{
return is_spike_of_collinear(qi(), qj(), qk());
}
return true;
}
}
return false;
}
private:
template <typename Point>
inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const
{
typedef model::referring_segment<Point const> seg_t;
typedef strategy_intersection
<
typename cs_tag<Point>::type, Point, Point, Point, RobustPolicy
> si;
typedef typename si::segment_intersection_strategy_type strategy;
typename strategy::return_type result
= strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy);
return result.template get<0>().count == 2;
}
template <std::size_t OpId>
bool is_ip_j() const
{
int arrival = d_info().arrival[OpId];
bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;
if ( same_dirs )
{
if ( i_info().count == 2 )
{
if ( ! d_info().opposite )
{
return arrival != -1;
}
else
{
return arrival != -1;
}
}
else
{
return arrival == 0;
}
}
else
{
return arrival == 1;
}
}
result_type m_result;
side_calculator_type m_side_calc;
RobustPolicy const& m_robust_policy;
};
// SEGMENT_INTERSECTION RESULT
// C H0 H1 A0 A1 O IP1 IP2
@@ -485,6 +321,8 @@ struct get_turn_info_for_endpoint
if ( append_first || append_last )
{
bool handled = handle_internal<0>(pi, pj, pk, qi, qj, qk,
inters.rpi(), inters.rpj(), inters.rpk(),
inters.rqi(), inters.rqj(), inters.rqk(),
is_p_first_ip, is_p_last_ip,
is_q_first_ip, is_q_last_ip,
ip_info.is_qi, ip_info.is_qj,
@@ -493,6 +331,8 @@ struct get_turn_info_for_endpoint
if ( !handled )
{
handle_internal<1>(qi, qj, qk, pi, pj, pk,
inters.rqi(), inters.rqj(), inters.rqk(),
inters.rpi(), inters.rpj(), inters.rpk(),
is_q_first_ip, is_q_last_ip,
is_p_first_ip, is_p_last_ip,
ip_info.is_pi, ip_info.is_pj,
@@ -549,11 +389,15 @@ struct get_turn_info_for_endpoint
template<std::size_t G1Index,
typename Point1,
typename Point2,
typename RobustPoint1,
typename RobustPoint2,
typename TurnInfo,
typename IntersectionInfo
>
static inline bool handle_internal(Point1 const& i1, Point1 const& j1, Point1 const& /*k1*/,
Point2 const& i2, Point2 const& j2, Point2 const& k2,
RobustPoint1 const& ri1, RobustPoint1 const& rj1, RobustPoint1 const& /*rk1*/,
RobustPoint2 const& ri2, RobustPoint2 const& rj2, RobustPoint2 const& rk2,
bool first1, bool last1, bool first2, bool last2,
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
IntersectionInfo const& inters, int ip_index,
@@ -582,7 +426,8 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
side_calculator<Point1, Point2, Point2> side_calc(i2, i1, j1, i2, j2, k2);
side_calculator<RobustPoint1, RobustPoint2, RobustPoint2>
side_calc(ri2, ri1, rj1, ri2, rj2, rk2);
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);
@@ -632,7 +477,8 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
side_calculator<Point1, Point2, Point2> side_calc(i2, j1, i1, i2, j2, k2);
side_calculator<RobustPoint1, RobustPoint2, RobustPoint2>
side_calc(ri2, rj1, ri1, ri2, rj2, rk2);
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_calc);

View File

@@ -0,0 +1,336 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013, 2014.
// Modifications copyright (c) 2013-2014 Oracle and/or its affiliates.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
namespace boost { namespace geometry {
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay {
enum turn_position { position_middle, position_front, position_back };
template <typename SegmentRatio>
struct turn_operation_linear
: public turn_operation<SegmentRatio>
{
turn_operation_linear()
: position(position_middle)
, is_collinear(false)
{}
turn_position position;
bool is_collinear; // valid only for Linear geometry
};
template <typename PointP, typename PointQ,
typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
>
struct side_calculator
{
typedef boost::geometry::strategy::side::side_by_triangle<> side; // todo: get from coordinate system
inline side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
Qi const& qi, Qj const& qj, Qk const& qk)
: m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
inline int pk_wrt_p1() const { return side::apply(m_pi, m_pj, m_pk); }
inline int pk_wrt_q1() const { return side::apply(m_qi, m_qj, m_pk); }
inline int qk_wrt_p1() const { return side::apply(m_pi, m_pj, m_qk); }
inline int qk_wrt_q1() const { return side::apply(m_qi, m_qj, m_qk); }
inline int pk_wrt_q2() const { return side::apply(m_qj, m_qk, m_pk); }
inline int qk_wrt_p2() const { return side::apply(m_pj, m_pk, m_qk); }
Pi const& m_pi;
Pj const& m_pj;
Pk const& m_pk;
Qi const& m_qi;
Qj const& m_qj;
Qk const& m_qk;
};
template <typename Point1, typename Point2, typename RobustPolicy>
struct robust_points
{
typedef typename geometry::robust_point_type
<
Point1, RobustPolicy
>::type robust_point1_type;
// TODO: define robust_point2_type using Point2?
typedef robust_point1_type robust_point2_type;
inline robust_points(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
{
geometry::recalculate(m_rpi, pi, robust_policy);
geometry::recalculate(m_rpj, pj, robust_policy);
geometry::recalculate(m_rpk, pk, robust_policy);
geometry::recalculate(m_rqi, qi, robust_policy);
geometry::recalculate(m_rqj, qj, robust_policy);
geometry::recalculate(m_rqk, qk, robust_policy);
}
robust_point1_type m_rpi, m_rpj, m_rpk;
robust_point2_type m_rqi, m_rqj, m_rqk;
};
template <typename Point1, typename Point2, typename RobustPolicy>
class intersection_info_base
: private robust_points<Point1, Point2, RobustPolicy>
{
typedef robust_points<Point1, Point2, RobustPolicy> base_t;
public:
typedef Point1 point1_type;
typedef Point2 point2_type;
typedef typename base_t::robust_point1_type robust_point1_type;
typedef typename base_t::robust_point2_type robust_point2_type;
typedef side_calculator<robust_point1_type, robust_point2_type> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
: base_t(pi, pj, pk, qi, qj, qk, robust_policy)
, m_side_calc(base_t::m_rpi, base_t::m_rpj, base_t::m_rpk,
base_t::m_rqi, base_t::m_rqj, base_t::m_rqk)
, m_pi(pi), m_pj(pj), m_pk(pk)
, m_qi(qi), m_qj(qj), m_qk(qk)
{}
inline Point1 const& pi() const { return m_pi; }
inline Point1 const& pj() const { return m_pj; }
inline Point1 const& pk() const { return m_pk; }
inline Point2 const& qi() const { return m_qi; }
inline Point2 const& qj() const { return m_qj; }
inline Point2 const& qk() const { return m_qk; }
inline robust_point1_type const& rpi() const { return base_t::m_rpi; }
inline robust_point1_type const& rpj() const { return base_t::m_rpj; }
inline robust_point1_type const& rpk() const { return base_t::m_rpk; }
inline robust_point2_type const& rqi() const { return base_t::m_rqi; }
inline robust_point2_type const& rqj() const { return base_t::m_rqj; }
inline robust_point2_type const& rqk() const { return base_t::m_rqk; }
inline side_calculator_type const& sides() const { return m_side_calc; }
private:
side_calculator_type m_side_calc;
point1_type const& m_pi;
point1_type const& m_pj;
point1_type const& m_pk;
point2_type const& m_qi;
point2_type const& m_qj;
point2_type const& m_qk;
};
template <typename Point1, typename Point2>
class intersection_info_base<Point1, Point2, detail::no_rescale_policy>
{
public:
typedef Point1 point1_type;
typedef Point2 point2_type;
typedef Point1 robust_point1_type;
typedef Point2 robust_point2_type;
typedef side_calculator<Point1, Point2> side_calculator_type;
intersection_info_base(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
no_rescale_policy const& robust_policy)
: m_side_calc(pi, pj, pk, qi, qj, qk)
{}
inline Point1 const& pi() const { return m_side_calc.m_pi; }
inline Point1 const& pj() const { return m_side_calc.m_pj; }
inline Point1 const& pk() const { return m_side_calc.m_pk; }
inline Point2 const& qi() const { return m_side_calc.m_qi; }
inline Point2 const& qj() const { return m_side_calc.m_qj; }
inline Point2 const& qk() const { return m_side_calc.m_qk; }
inline Point1 const& rpi() const { return pi(); }
inline Point1 const& rpj() const { return pj(); }
inline Point1 const& rpk() const { return pk(); }
inline Point2 const& rqi() const { return qi(); }
inline Point2 const& rqj() const { return qj(); }
inline Point2 const& rqk() const { return qk(); }
inline side_calculator_type const& sides() const { return m_side_calc; }
private:
side_calculator_type m_side_calc;
};
template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
class intersection_info
: public intersection_info_base<Point1, Point2, RobustPolicy>
{
typedef intersection_info_base<Point1, Point2, RobustPolicy> base_t;
typedef typename strategy_intersection
<
typename cs_tag<TurnPoint>::type,
Point1,
Point2,
TurnPoint,
RobustPolicy
>::segment_intersection_strategy_type strategy;
public:
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
typedef typename base_t::side_calculator_type side_calculator_type;
typedef typename strategy::return_type result_type;
typedef typename boost::tuples::element<0, result_type>::type i_info_type; // intersection_info
typedef typename boost::tuples::element<1, result_type>::type d_info_type; // dir_info
intersection_info(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
: base_t(pi, pj, pk, qi, qj, qk, robust_policy)
, m_result(strategy::apply(segment_type1(pi, pj),
segment_type2(qi, qj),
robust_policy))
, m_robust_policy(robust_policy)
{}
inline result_type const& result() const { return m_result; }
inline i_info_type const& i_info() const { return m_result.template get<0>(); }
inline d_info_type const& d_info() const { return m_result.template get<1>(); }
// TODO: it's more like is_spike_ip_p
inline bool is_spike_p() const
{
if ( base_t::sides().pk_wrt_p1() == 0 )
{
if ( ! is_ip_j<0>() )
return false;
int const qk_p1 = base_t::sides().qk_wrt_p1();
int const qk_p2 = base_t::sides().qk_wrt_p2();
if ( qk_p1 == -qk_p2 )
{
if ( qk_p1 == 0 )
{
return is_spike_of_collinear(base_t::pi(), base_t::pj(), base_t::pk());
}
return true;
}
}
return false;
}
// TODO: it's more like is_spike_ip_q
inline bool is_spike_q() const
{
if ( base_t::sides().qk_wrt_q1() == 0 )
{
if ( ! is_ip_j<1>() )
return false;
int const pk_q1 = base_t::sides().pk_wrt_q1();
int const pk_q2 = base_t::sides().pk_wrt_q2();
if ( pk_q1 == -pk_q2 )
{
if ( pk_q1 == 0 )
{
return is_spike_of_collinear(base_t::qi(), base_t::qj(), base_t::qk());
}
return true;
}
}
return false;
}
private:
template <typename Point>
inline bool is_spike_of_collinear(Point const& i, Point const& j, Point const& k) const
{
typedef model::referring_segment<Point const> seg_t;
typedef strategy_intersection
<
typename cs_tag<Point>::type, Point, Point, Point, RobustPolicy
> si;
typedef typename si::segment_intersection_strategy_type strategy;
typename strategy::return_type result
= strategy::apply(seg_t(i, j), seg_t(j, k), m_robust_policy);
return result.template get<0>().count == 2;
}
template <std::size_t OpId>
bool is_ip_j() const
{
int arrival = d_info().arrival[OpId];
bool same_dirs = d_info().dir_a == 0 && d_info().dir_b == 0;
if ( same_dirs )
{
if ( i_info().count == 2 )
{
if ( ! d_info().opposite )
{
return arrival != -1;
}
else
{
return arrival != -1;
}
}
else
{
return arrival == 0;
}
}
else
{
return arrival == 1;
}
}
result_type m_result;
RobustPolicy const& m_robust_policy;
};
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HELPERS_HPP

View File

@@ -47,8 +47,10 @@ struct get_turn_info_linear_areal
RobustPolicy const& robust_policy,
OutputIterator out)
{
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters(pi, pj, pk, qi, qj, qk, robust_policy);
typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters_info;
inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
char const method = inters.d_info().how;
@@ -64,7 +66,7 @@ struct get_turn_info_linear_areal
get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, inters.result(), method_none, out);
tp_model, inters, method_none, out);
break;
case 'd' : // disjoint: never do anything
@@ -75,7 +77,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<false, true>(
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, inters.result(), method_touch_interior, out) )
tp_model, inters, method_touch_interior, out) )
{
// do nothing
}
@@ -96,7 +98,12 @@ struct get_turn_info_linear_areal
else
{
// Swap p/q
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
side_calculator
<
typename inters_info::robust_point2_type,
typename inters_info::robust_point1_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
inters.rpi(), inters.rpj(), inters.rpk());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
@@ -138,7 +145,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<false, true>(
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, inters.result(), method_touch, out) )
tp_model, inters, method_touch, out) )
{
// do nothing
}
@@ -230,7 +237,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, inters.result(), method_equal, out) )
tp_model, inters, method_equal, out) )
{
// do nothing
}
@@ -277,7 +284,7 @@ struct get_turn_info_linear_areal
if ( get_turn_info_for_endpoint<true, true>(
pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, inters.result(), method_collinear, out) )
tp_model, inters, method_collinear, out) )
{
// do nothing
}
@@ -621,7 +628,7 @@ struct get_turn_info_linear_areal
typename Point1,
typename Point2,
typename TurnInfo,
typename IntersectionResult,
typename IntersectionInfo,
typename OutputIterator>
static inline bool get_turn_info_for_endpoint(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
@@ -629,14 +636,14 @@ struct get_turn_info_linear_areal
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
IntersectionResult const& result,
IntersectionInfo const& inters,
method_type /*method*/,
OutputIterator out)
{
namespace ov = overlay;
typedef ov::get_turn_info_for_endpoint<AssignPolicy, EnableFirst, EnableLast> get_info_e;
const std::size_t ip_count = result.template get<0>().count;
const std::size_t ip_count = inters.i_info().count;
// no intersection points
if ( ip_count == 0 )
return false;
@@ -648,11 +655,11 @@ struct get_turn_info_linear_areal
if ( !is_p_first && !is_p_last )
return false;
linear_intersections intersections(pi, qi, result, is_p_last, is_q_last);
linear_intersections intersections(pi, qi, inters.result(), is_p_last, is_q_last);
linear_intersections::ip_info const& ip0 = intersections.template get<0>();
linear_intersections::ip_info const& ip1 = intersections.template get<1>();
const bool opposite = result.template get<1>().opposite;
const bool opposite = inters.d_info().opposite;
// ANALYSE AND ASSIGN FIRST
@@ -675,7 +682,13 @@ struct get_turn_info_linear_areal
if ( ip0.is_qj )
{
side_calculator<Point1, Point2, Point2> side_calc(qi, pi, pj, qi, qj, qk);
side_calculator
<
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
typename IntersectionInfo::robust_point2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
inters.rqi(), inters.rqj(), inters.rqk());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -687,9 +700,18 @@ struct get_turn_info_linear_areal
}
else
{
side_calculator<Point1, Point2,
Point2, Point1, Point1,
Point2, Point1, Point2> side_calc(qi, pi, pj, qi, pi, qj);
side_calculator
<
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
typename IntersectionInfo::robust_point2_type,
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type
> side_calc(inters.rqi(), inters.rpi(), inters.rpj(),
inters.rqi(), inters.rpi(), inters.rqj());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -704,17 +726,17 @@ struct get_turn_info_linear_areal
// equals<> or collinear<> will assign the second point,
// we'd like to assign the first one
base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), 0);
base_turn_handler::assign_point(tp, tp.method, inters.i_info(), 0);
// NOTE: not really needed especially for the first point
// for which there is no preceding segment (but consistent with the L/L)
if ( result.template get<0>().count > 1 )
if ( inters.i_info().count > 1 )
{
//BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
tp.operations[0].is_collinear = true;
}
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
}
@@ -727,7 +749,7 @@ struct get_turn_info_linear_areal
{
TurnInfo tp = tp_model;
if ( result.template get<0>().count > 1 )
if ( inters.i_info().count > 1 )
{
//BOOST_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
tp.operations[0].is_collinear = true;
@@ -735,7 +757,13 @@ struct get_turn_info_linear_areal
}
else //if ( result.template get<0>().count == 1 )
{
side_calculator<Point1, Point2, Point2> side_calc(qi, pj, pi, qi, qj, qk);
side_calculator
<
typename IntersectionInfo::robust_point1_type,
typename IntersectionInfo::robust_point2_type,
typename IntersectionInfo::robust_point2_type
> side_calc(inters.rqi(), inters.rpj(), inters.rpi(),
inters.rqi(), inters.rqj(), inters.rqk());
std::pair<operation_type, operation_type>
operations = get_info_e::operations_of_equal(side_calc);
@@ -760,9 +788,9 @@ struct get_turn_info_linear_areal
// equals<> or collinear<> will assign the second point,
// we'd like to assign the first one
std::size_t ip_index = ip_count > 1 ? 1 : 0;
base_turn_handler::assign_point(tp, tp.method, result.template get<0>(), ip_index);
base_turn_handler::assign_point(tp, tp.method, inters.i_info(), ip_index);
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
*out++ = tp;
return true;

View File

@@ -44,8 +44,10 @@ struct get_turn_info_linear_linear
RobustPolicy const& robust_policy,
OutputIterator out)
{
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters(pi, pj, pk, qi, qj, qk, robust_policy);
typedef intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters_info;
inters_info inters(pi, pj, pk, qi, qj, qk, robust_policy);
char const method = inters.d_info().how;
@@ -93,7 +95,13 @@ struct get_turn_info_linear_linear
else
{
// Swap p/q
side_calculator<Point2, Point1> swapped_side_calc(qi, qj, qk, pi, pj, pk);
side_calculator
<
typename inters_info::robust_point2_type,
typename inters_info::robust_point1_type
> swapped_side_calc(inters.rqi(), inters.rqj(), inters.rqk(),
inters.rpi(), inters.rpj(), inters.rpk());
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);