[get_turns] Refactor get_turns for L/L and L/A.

This change prevents duplication and decreases the number of parameters that must be passed to various functions and makes the code more readable.

Enclose parts of the code used in both implementations in one class - intersection_info. Move there IntersectionsResult, sides_calculator, spikes checks. Use this class in get_turn_info_linear_*. Provide convenient i_info() and d_info() to allow replacing result.template get<0>() and result.template get<1>() calls.
This commit is contained in:
Adam Wulkiewicz
2014-04-26 03:03:58 +02:00
parent 80654aea65
commit f671b5830f
3 changed files with 253 additions and 321 deletions

View File

@@ -38,96 +38,116 @@ struct turn_operation_linear
bool is_collinear; // valid only for Linear geometry
};
// IS_SPIKE
template <typename Point, typename RobustPolicy>
inline bool is_spike_of_collinear(model::referring_segment<Point const> const& s1,
model::referring_segment<Point const> const& s2,
RobustPolicy const& robust_policy)
template <typename Point1, typename Point2, typename TurnPoint, typename RobustPolicy>
class intersection_info
{
typedef strategy_intersection
typedef typename 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(s1, s2, robust_policy);
return result.template get<0>().count == 2;
}
typename cs_tag<TurnPoint>::type,
Point1,
Point2,
TurnPoint,
RobustPolicy
>::segment_intersection_strategy_type strategy;
template <typename Point1, typename Point2, typename RobustPolicy>
inline bool is_spike_p(side_calculator<Point1, Point2> const& side_calc,
model::referring_segment<Point1 const> const& p1,
model::referring_segment<Point1 const> const& p2,
RobustPolicy const& robust_policy)
{
if ( side_calc.pk_wrt_p1() == 0 )
{
int const qk_p1 = side_calc.qk_wrt_p1();
int const qk_p2 = side_calc.qk_wrt_p2();
if ( qk_p1 == -qk_p2 )
{
if ( qk_p1 == 0 )
{
return is_spike_of_collinear(p1, p2, robust_policy);
}
return true;
}
}
return false;
}
template <typename Point1, typename Point2, typename RobustPolicy>
inline bool is_spike_q(side_calculator<Point1, Point2> const& side_calc,
model::referring_segment<Point2 const> const& q1,
model::referring_segment<Point2 const> const& q2,
RobustPolicy const& robust_policy)
{
if ( side_calc.qk_wrt_q1() == 0 )
{
int const pk_q1 = side_calc.pk_wrt_q1();
int const pk_q2 = side_calc.pk_wrt_q2();
if ( pk_q1 == -pk_q2 )
{
if ( pk_q1 == 0 )
{
return is_spike_of_collinear(q1, q2, robust_policy);
}
return true;
}
}
return false;
}
template <typename Point1, typename Point2, typename RobustPolicy>
inline bool is_spike_p(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
{
public:
typedef model::referring_segment<Point1 const> segment_type1;
segment_type1 p1(pi, pj), p2(pj, pk);
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
return is_spike_p(side_calc, p1, p2, robust_policy);
}
template <typename Point1, typename Point2, typename RobustPolicy>
inline bool is_spike_q(Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
RobustPolicy const& robust_policy)
{
typedef model::referring_segment<Point2 const> segment_type2;
segment_type2 q1(qi, qj), q2(qj, qk);
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
return is_spike_q(side_calc, q1, q2, robust_policy);
}
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>(); }
inline bool is_spike_p() const
{
if ( m_side_calc.pk_wrt_p1() == 0 )
{
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(segment_type1(pi(), pj()),
segment_type1(pj(), pk()));
}
return true;
}
}
return false;
}
inline bool is_spike_q() const
{
if ( m_side_calc.qk_wrt_q1() == 0 )
{
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(segment_type2(qi(), qj()),
segment_type2(qj(), qk()));
}
return true;
}
}
return false;
}
private:
template <typename Point>
inline bool is_spike_of_collinear(
model::referring_segment<Point const> const& s1,
model::referring_segment<Point const> const& s2) const
{
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(s1, s2, m_robust_policy);
return result.template get<0>().count == 2;
}
result_type m_result;
side_calculator_type m_side_calc;
RobustPolicy const& m_robust_policy;
};
// SEGMENT_INTERSECTION RESULT
@@ -335,8 +355,7 @@ struct get_turn_info_for_endpoint
template<typename Point1,
typename Point2,
typename TurnInfo,
typename IntersectionResult,
typename RobustPolicy,
typename IntersectionInfo,
typename OutputIterator
>
static inline bool apply(Point1 const& pi, Point1 const& pj, Point1 const& pk,
@@ -344,12 +363,11 @@ struct get_turn_info_for_endpoint
bool is_p_first, bool is_p_last,
bool is_q_first, bool is_q_last,
TurnInfo const& tp_model,
IntersectionResult const& result,
RobustPolicy const& robust_policy,
IntersectionInfo const& inters,
method_type /*method*/,
OutputIterator out)
{
std::size_t ip_count = result.template get<0>().count;
std::size_t ip_count = inters.i_info().count;
// no intersection points
if ( ip_count == 0 )
return false;
@@ -361,17 +379,16 @@ struct get_turn_info_for_endpoint
if ( !is_p_first && !is_p_last && !is_q_first && !is_q_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);
bool append0_last
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
intersections.template get<0>(),
tp_model, result, 0,
robust_policy, out);
tp_model, inters, 0, out);
// NOTE: opposite && ip_count == 1 may be true!
bool opposite = result.template get<1>().opposite;
bool opposite = inters.d_info().opposite;
// don't ignore only for collinear opposite
bool result_ignore_ip0 = append0_last && ( ip_count == 1 || !opposite );
@@ -383,8 +400,7 @@ struct get_turn_info_for_endpoint
= analyse_segment_and_assign_ip(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
intersections.template get<1>(),
tp_model, result, 1,
robust_policy, out);
tp_model, inters, 1, out);
// don't ignore only for collinear opposite
bool result_ignore_ip1 = append1_last && !opposite /*&& ip_count == 2*/;
@@ -395,8 +411,7 @@ struct get_turn_info_for_endpoint
template <typename Point1,
typename Point2,
typename TurnInfo,
typename IntersectionResult,
typename RobustPolicy,
typename IntersectionInfo,
typename OutputIterator>
static inline
bool analyse_segment_and_assign_ip(Point1 const& pi, Point1 const& pj, Point1 const& pk,
@@ -405,9 +420,8 @@ struct get_turn_info_for_endpoint
bool is_q_first, bool is_q_last,
linear_intersections::ip_info const& ip_info,
TurnInfo const& tp_model,
IntersectionResult const& result,
IntersectionInfo const& inters,
int ip_index,
RobustPolicy const& robust_policy,
OutputIterator out)
{
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS_LINEAR_LINEAR
@@ -437,14 +451,16 @@ struct get_turn_info_for_endpoint
is_p_first_ip, is_p_last_ip,
is_q_first_ip, is_q_last_ip,
ip_info.is_qi, ip_info.is_qj,
tp_model, result, ip_index, p_operation, q_operation);
tp_model, inters.result(), ip_index,
p_operation, q_operation);
if ( !handled )
{
handle_internal(qi, qj, qk, pi, pj, pk,
is_q_first_ip, is_q_last_ip,
is_p_first_ip, is_p_last_ip,
ip_info.is_pi, ip_info.is_pj,
tp_model, result, ip_index, q_operation, p_operation);
tp_model, inters.result(), ip_index,
q_operation, p_operation);
}
if ( p_operation != operation_none )
@@ -458,28 +474,28 @@ struct get_turn_info_for_endpoint
// P is spike and should be handled
if ( !is_p_last && ip_info.is_pj
&& result.template get<0>().count == 2
&& is_spike_p(pi, pj, pk, qi, qj, qk, robust_policy) )
&& inters.i_info().count == 2
&& inters.is_spike_p() )
{
assign(pi, qi, result, ip_index, method, operation_blocked, q_operation,
assign(pi, qi, inters.result(), ip_index, method, operation_blocked, q_operation,
p_pos, q_pos, tp_model, out);
assign(pi, qi, result, ip_index, method, operation_intersection, q_operation,
assign(pi, qi, inters.result(), ip_index, method, operation_intersection, q_operation,
p_pos, q_pos, tp_model, out);
}
// Q is spike and should be handled
else if ( !is_q_last && ip_info.is_qj
&& result.template get<0>().count == 2
&& is_spike_q(pi, pj, pk, qi, qj, qk, robust_policy) )
&& inters.i_info().count == 2
&& inters.is_spike_q() )
{
assign(pi, qi, result, ip_index, method, p_operation, operation_blocked,
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_blocked,
p_pos, q_pos, tp_model, out);
assign(pi, qi, result, ip_index, method, p_operation, operation_intersection,
assign(pi, qi, inters.result(), ip_index, method, p_operation, operation_intersection,
p_pos, q_pos, tp_model, out);
}
// no spikes
else
{
assign(pi, qi, result, ip_index, method, p_operation, q_operation,
assign(pi, qi, inters.result(), ip_index, method, p_operation, q_operation,
p_pos, q_pos, tp_model, out);
}
}
@@ -498,12 +514,9 @@ struct get_turn_info_for_endpoint
>
static inline bool handle_internal(Point1 const& i1, Point1 const& j1, Point1 const& /*k1*/,
Point2 const& i2, Point2 const& j2, Point2 const& k2,
bool first1, bool last1,
bool first2, bool last2,
bool ip_i2, bool ip_j2,
TurnInfo const& tp_model,
IntersectionResult const& result,
int ip_index,
bool first1, bool last1, bool first2, bool last2,
bool ip_i2, bool ip_j2, TurnInfo const& tp_model,
IntersectionResult const& result, int ip_index,
operation_type & op1, operation_type & op2)
{
boost::ignore_unused_variable_warning(ip_index);

View File

@@ -47,27 +47,10 @@ struct get_turn_info_linear_areal
RobustPolicy const& robust_policy,
OutputIterator out)
{
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj), p2(pj, pk);
segment_type2 q1(qi, qj), q2(qj, qk);
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters(pi, pj, pk, qi, qj, qk, robust_policy);
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
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);
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;
@@ -81,7 +64,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, result, method_none, out);
tp_model, inters.result(), method_none, out);
break;
case 'd' : // disjoint: never do anything
@@ -92,7 +75,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, result, method_touch_interior, out) )
tp_model, inters.result(), method_touch_interior, out) )
{
// do nothing
}
@@ -104,18 +87,18 @@ struct get_turn_info_linear_areal
> 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);
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);
}
@@ -130,10 +113,9 @@ struct get_turn_info_linear_areal
// this function assumes that 'u' must be set for a spike
calculate_spike_operation(tp.operations[0].operation,
side_calc, p1, p2,
is_p_last, robust_policy);
inters, is_p_last);
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;
}
@@ -142,11 +124,11 @@ struct get_turn_info_linear_areal
case 'i' :
{
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
tp, inters.i_info(), inters.d_info());
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
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;
@@ -156,14 +138,14 @@ 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, result, method_touch, out) )
tp_model, inters.result(), method_touch, out) )
{
// do nothing
}
else
{
touch<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());
if ( tp.operations[1].operation == operation_blocked )
{
@@ -177,19 +159,15 @@ struct get_turn_info_linear_areal
// this function assumes that 'u' must be set for a spike
bool ignore_spike
= calculate_spike_operation(tp.operations[0].operation,
side_calc, p1, p2,
is_p_last, robust_policy);
inters, is_p_last);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
if ( ! handle_spikes
|| ignore_spike
|| ! append_opposite_spikes<append_touches>( // for 'i' or 'c'
tp, result, side_calc,
p1, p2, q1, q2,
is_p_last, is_q_last,
robust_policy, out) )
tp, inters, is_p_last, is_q_last, out) )
{
*out++ = tp;
}
@@ -201,7 +179,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, result, method_equal, out) )
tp_model, inters.result(), method_equal, out) )
{
// do nothing
}
@@ -209,26 +187,23 @@ struct get_turn_info_linear_areal
{
tp.operations[0].is_collinear = true;
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);
tp, inters.i_info(), inters.d_info(), inters.sides());
replacer_of_method_and_operations_ec<false> replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
// conditionally handle spikes
if ( ! handle_spikes
|| ! append_collinear_spikes(
tp, side_calc, p1, p2, q1, q2,
is_p_last, is_q_last,
method_touch, append_equal,
robust_policy, out) )
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
method_touch, append_equal, out) )
{
*out++ = tp; // no spikes
}
@@ -240,7 +215,7 @@ struct get_turn_info_linear_areal
TurnInfo,
AssignPolicy
>::apply(pi, qi,
tp, out, result.template get<0>(), result.template get<1>());
tp, out, inters.i_info(), inters.d_info());
}
}
}
@@ -251,7 +226,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, result, method_collinear, out) )
tp_model, inters.result(), method_collinear, out) )
{
// do nothing
}
@@ -259,16 +234,16 @@ struct get_turn_info_linear_areal
{
tp.operations[0].is_collinear = true;
if (! result.template get<1>().opposite)
if ( ! inters.d_info().opposite )
{
method_type method_replace = method_touch_interior;
append_version_c version = append_collinear;
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());
method_replace = method_touch;
version = append_equal;
@@ -276,7 +251,7 @@ struct get_turn_info_linear_areal
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());
//method_replace = method_touch_interior;
//version = append_collinear;
@@ -286,15 +261,12 @@ struct get_turn_info_linear_areal
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
// conditionally handle spikes
if ( ! handle_spikes
|| ! append_collinear_spikes(
tp, side_calc, p1, p2, q1, q2,
is_p_last, is_q_last,
method_replace, version,
robust_policy, out) )
|| ! append_collinear_spikes(tp, inters, is_p_last, is_q_last,
method_replace, version, out) )
{
// no spikes
*out++ = tp;
@@ -309,10 +281,7 @@ struct get_turn_info_linear_areal
if ( handle_spikes )
{
append_opposite_spikes<append_collinear_opposite>(
tp, result, side_calc,
p1, p2, q1, q2,
is_p_last, is_q_last,
robust_policy, out);
tp, inters, is_p_last, is_q_last, out);
}
// TODO: ignore for spikes?
@@ -324,8 +293,8 @@ struct get_turn_info_linear_areal
TurnInfo,
AssignPolicy
>::apply(pi, pj, pk, qi, qj, qk,
tp, out, result.template get<0>(), result.template get<1>(), side_calc,
replacer);
tp, out, inters.i_info(), inters.d_info(),
inters.sides(), replacer);
}
}
}
@@ -335,7 +304,7 @@ struct get_turn_info_linear_areal
// degenerate points
if (AssignPolicy::include_degenerate)
{
only_convert::apply(tp, result.template get<0>());
only_convert::apply(tp, inters.i_info());
if ( is_p_first
&& equals::equals_point_point(pi, tp.point) )
@@ -349,7 +318,7 @@ struct get_turn_info_linear_areal
}
// tp.operations[1].position = position_middle;
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;
}
}
@@ -370,24 +339,19 @@ struct get_turn_info_linear_areal
}
template <typename Operation,
typename SideCalc,
typename PSegment,
typename RobustPolicy>
typename IntersectionInfo>
static inline bool calculate_spike_operation(Operation & op,
SideCalc const& side_calc,
PSegment const& p1,
PSegment const& p2,
bool is_p_last,
RobustPolicy const& robust_policy)
IntersectionInfo const& inters,
bool is_p_last)
{
bool is_p_spike = op == operation_union
&& ! is_p_last
&& is_spike_p(side_calc, p1, p2, robust_policy);
&& inters.is_spike_p();
// we don't know where the spike is going since for both directions 'u' is set
if ( is_p_spike )
{
if ( side_calc.pk_wrt_q1() < 0 && side_calc.pk_wrt_q2() < 0 )
if ( inters.sides().pk_wrt_q1() < 0 && inters.sides().pk_wrt_q2() < 0 )
{
op = operation_intersection;
return true;
@@ -400,18 +364,13 @@ struct get_turn_info_linear_areal
enum append_version_c { append_equal, append_collinear };
template <typename TurnInfo,
typename SideCalc,
typename SegmentP,
typename SegmentQ,
typename RobustPolicy,
typename IntersectionInfo,
typename OutIt>
static inline bool append_collinear_spikes(TurnInfo & tp,
SideCalc const& side_calc,
SegmentP const& p1, SegmentP const& p2,
SegmentQ const& q1, SegmentQ const& q2,
IntersectionInfo const& inters,
bool is_p_last, bool is_q_last,
method_type method, append_version_c version,
RobustPolicy const& robust_policy, OutIt out)
OutIt out)
{
// method == touch || touch_interior
// both position == middle
@@ -421,12 +380,12 @@ struct get_turn_info_linear_areal
|| tp.operations[0].operation == operation_intersection ) :
tp.operations[0].operation == operation_continue )
&& ! is_p_last
&& is_spike_p(side_calc, p1, p2, robust_policy);
&& inters.is_spike_p();
// TODO: throw an exception for spike in Areal?
/*bool is_q_spike = tp.operations[1].operation == spike_op
&& ! is_q_last
&& is_spike_q(side_calc, q1, q2, robust_policy);*/
&& inters.is_spike_q();*/
if ( is_p_spike )
{
@@ -448,35 +407,28 @@ struct get_turn_info_linear_areal
template <append_version_o Version,
typename TurnInfo,
typename Result,
typename SideCalc,
typename SegmentP,
typename SegmentQ,
typename RobustPolicy,
typename IntersectionInfo,
typename OutIt>
static inline bool append_opposite_spikes(TurnInfo & tp,
Result const& result,
SideCalc const& side_calc,
SegmentP const& p1, SegmentP const& p2,
SegmentQ const& q1, SegmentQ const& q2,
IntersectionInfo const& inters,
bool is_p_last, bool is_q_last,
RobustPolicy const& robust_policy, OutIt out)
OutIt out)
{
bool is_p_spike = ( Version == append_touches ?
( tp.operations[0].operation == operation_continue
|| tp.operations[0].operation == operation_intersection ) :
true )
&& ! is_p_last
&& is_spike_p(side_calc, p1, p2, robust_policy);
&& inters.is_spike_p();
// TODO: throw an exception for spike in Areal?
/*bool is_q_spike = ( Version == append_touches ?
( tp.operations[1].operation == operation_continue
|| tp.operations[1].operation == operation_intersection ) :
true )
&& ! is_q_last
&& is_spike_q(side_calc, q1, q2, robust_policy);*/
&& inters.is_spike_q();*/
if ( is_p_spike && ( Version == append_touches || result.template get<1>().arrival[0] == 1 ) )
if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
{
if ( Version == append_touches )
{
@@ -489,12 +441,10 @@ struct get_turn_info_linear_areal
//tp.operations[0].is_collinear = true;
//tp.operations[1].is_collinear = true;
//tp.method = method_touch_interior; // only because arrival != 0
BOOST_ASSERT(result.template get<0>().count > 1);
//geometry::convert(result.template get<0>().intersections[1], tp.point);
base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 1);
BOOST_ASSERT(inters.i_info().count > 1);
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 1);
AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, inters.pi(), inters.qi(), inters.i_info(), inters.d_info());
}
tp.operations[0].operation = operation_blocked;

View File

@@ -44,27 +44,10 @@ struct get_turn_info_linear_linear
RobustPolicy const& robust_policy,
OutputIterator out)
{
typedef model::referring_segment<Point1 const> segment_type1;
typedef model::referring_segment<Point2 const> segment_type2;
segment_type1 p1(pi, pj), p2(pj, pk);
segment_type2 q1(qi, qj), q2(qj, qk);
intersection_info<Point1, Point2, typename TurnInfo::point_type, RobustPolicy>
inters(pi, pj, pk, qi, qj, qk, robust_policy);
side_calculator<Point1, Point2> side_calc(pi, pj, pk, qi, qj, qk);
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);
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;
@@ -78,7 +61,7 @@ struct get_turn_info_linear_linear
get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, robust_policy, method_none, out);
tp_model, inters, method_none, out);
break;
case 'd' : // disjoint: never do anything
@@ -89,7 +72,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, robust_policy, method_touch_interior, out) )
tp_model, inters, method_touch_interior, out) )
{
// do nothing
}
@@ -101,19 +84,19 @@ struct get_turn_info_linear_linear
> 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);
policy::template apply<1>(qi, qj, qk, pi, pj, pk,
tp, result.template get<0>(), result.template get<1>(),
swapped_side_calc);
tp, inters.i_info(), inters.d_info(),
swapped_side_calc);
}
if ( tp.operations[0].operation == operation_blocked )
@@ -125,9 +108,11 @@ struct get_turn_info_linear_linear
tp.operations[0].is_collinear = true;
}
replace_method_and_operations_tm(tp.method, tp.operations[0].operation, tp.operations[1].operation);
replace_method_and_operations_tm(tp.method,
tp.operations[0].operation,
tp.operations[1].operation);
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;
}
}
@@ -135,11 +120,11 @@ struct get_turn_info_linear_linear
case 'i' :
{
crosses<TurnInfo>::apply(pi, pj, pk, qi, qj, qk,
tp, result.template get<0>(), result.template get<1>());
tp, inters.i_info(), inters.d_info());
replace_operations_i(tp.operations[0].operation, tp.operations[1].operation);
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;
@@ -149,14 +134,14 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<AssignPolicy, false, true>
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, robust_policy, method_touch, out) )
tp_model, inters, method_touch, out) )
{
// do nothing
}
else
{
touch<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());
if ( tp.operations[0].operation == operation_blocked )
{
@@ -172,14 +157,12 @@ struct get_turn_info_linear_linear
tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
if ( ! handle_spikes
|| ! append_opposite_spikes<append_touches>(
tp, result, side_calc,
p1, p2, q1, q2,
is_p_last, is_q_last,
robust_policy, out) )
|| ! append_opposite_spikes<append_touches>(tp, inters,
is_p_last, is_q_last,
out) )
{
*out++ = tp;
}
@@ -191,7 +174,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, robust_policy, method_equal, out) )
tp_model, inters, method_equal, out) )
{
// do nothing
}
@@ -200,25 +183,25 @@ struct get_turn_info_linear_linear
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = true;
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);
tp, inters.i_info(), inters.d_info(), inters.sides());
replacer_of_method_and_operations_ec replacer(method_touch);
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
// conditionally handle spikes
if ( ! handle_spikes
|| ! append_collinear_spikes(tp, side_calc, p1, p2, q1, q2,
|| ! append_collinear_spikes(tp, inters,
is_p_last, is_q_last,
method_touch, operation_union,
robust_policy, out) )
out) )
{
*out++ = tp; // no spikes
}
@@ -231,8 +214,7 @@ struct get_turn_info_linear_linear
<
TurnInfo,
AssignPolicy
>::apply(pi, qi,
tp, out, result.template get<0>(), result.template get<1>());
>::apply(pi, qi, tp, out, inters.i_info(), inters.d_info());
}
}
}
@@ -243,7 +225,7 @@ struct get_turn_info_linear_linear
if ( get_turn_info_for_endpoint<AssignPolicy, true, true>
::apply(pi, pj, pk, qi, qj, qk,
is_p_first, is_p_last, is_q_first, is_q_last,
tp_model, result, robust_policy, method_collinear, out) )
tp_model, inters, method_collinear, out) )
{
// do nothing
}
@@ -252,16 +234,16 @@ struct get_turn_info_linear_linear
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = true;
if (! result.template get<1>().opposite)
if ( ! inters.d_info().opposite )
{
method_type method_replace = method_touch_interior;
operation_type spike_op = operation_continue;
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());
method_replace = method_touch;
spike_op = operation_union;
@@ -269,7 +251,7 @@ struct get_turn_info_linear_linear
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());
//method_replace = method_touch_interior;
//spike_op = operation_continue;
@@ -279,14 +261,14 @@ struct get_turn_info_linear_linear
replacer(tp.method, tp.operations[0].operation, tp.operations[1].operation);
// TODO: move this into the append_xxx and call for each turn?
AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, pi, qi, inters.i_info(), inters.d_info());
// conditionally handle spikes
if ( ! handle_spikes
|| ! append_collinear_spikes(tp, side_calc, p1, p2, q1, q2,
|| ! append_collinear_spikes(tp, inters,
is_p_last, is_q_last,
method_replace, spike_op,
robust_policy, out) )
out) )
{
// no spikes
*out++ = tp;
@@ -300,11 +282,9 @@ struct get_turn_info_linear_linear
// conditionally handle spikes
if ( handle_spikes )
{
append_opposite_spikes<append_collinear_opposite>(
tp, result, side_calc,
p1, p2, q1, q2,
is_p_last, is_q_last,
robust_policy, out);
append_opposite_spikes<append_collinear_opposite>(tp, inters,
is_p_last, is_q_last,
out);
}
// TODO: ignore for spikes?
@@ -316,7 +296,7 @@ struct get_turn_info_linear_linear
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(),
replacer, !is_p_last, !is_q_last);
}
}
@@ -327,7 +307,7 @@ struct get_turn_info_linear_linear
// degenerate points
if (AssignPolicy::include_degenerate)
{
only_convert::apply(tp, result.template get<0>());
only_convert::apply(tp, inters.i_info());
// if any, only one of those should be true
if ( is_p_first
@@ -351,7 +331,7 @@ struct get_turn_info_linear_linear
tp.operations[1].position = position_back;
}
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;
}
}
@@ -372,28 +352,23 @@ struct get_turn_info_linear_linear
}
template <typename TurnInfo,
typename SideCalc,
typename SegmentP,
typename SegmentQ,
typename RobustPolicy,
typename IntersectionInfo,
typename OutIt>
static inline bool append_collinear_spikes(TurnInfo & tp,
SideCalc const& side_calc,
SegmentP const& p1, SegmentP const& p2,
SegmentQ const& q1, SegmentQ const& q2,
IntersectionInfo const& inters_info,
bool is_p_last, bool is_q_last,
method_type method, operation_type spike_op,
RobustPolicy const& robust_policy, OutIt out)
OutIt out)
{
// method == touch || touch_interior
// both position == middle
bool is_p_spike = tp.operations[0].operation == spike_op
&& ! is_p_last
&& is_spike_p(side_calc, p1, p2, robust_policy);
&& inters_info.is_spike_p();
bool is_q_spike = tp.operations[1].operation == spike_op
&& ! is_q_last
&& is_spike_q(side_calc, q1, q2, robust_policy);
&& inters_info.is_spike_q();
if ( is_p_spike && is_q_spike )
{
@@ -439,36 +414,29 @@ struct get_turn_info_linear_linear
template <append_version Version,
typename TurnInfo,
typename Result,
typename SideCalc,
typename SegmentP,
typename SegmentQ,
typename RobustPolicy,
typename IntersectionInfo,
typename OutIt>
static inline bool append_opposite_spikes(TurnInfo & tp,
Result const& result,
SideCalc const& side_calc,
SegmentP const& p1, SegmentP const& p2,
SegmentQ const& q1, SegmentQ const& q2,
IntersectionInfo const& inters,
bool is_p_last, bool is_q_last,
RobustPolicy const& robust_policy, OutIt out)
OutIt out)
{
bool is_p_spike = ( Version == append_touches ?
( tp.operations[0].operation == operation_continue
|| tp.operations[0].operation == operation_intersection ) :
true )
&& ! is_p_last
&& is_spike_p(side_calc, p1, p2, robust_policy);
&& inters.is_spike_p();
bool is_q_spike = ( Version == append_touches ?
( tp.operations[1].operation == operation_continue
|| tp.operations[1].operation == operation_intersection ) :
true )
&& ! is_q_last
&& is_spike_q(side_calc, q1, q2, robust_policy);
&& inters.is_spike_q();
bool res = false;
if ( is_p_spike && ( Version == append_touches || result.template get<1>().arrival[0] == 1 ) )
if ( is_p_spike && ( Version == append_touches || inters.d_info().arrival[0] == 1 ) )
{
if ( Version == append_touches )
{
@@ -481,12 +449,13 @@ struct get_turn_info_linear_linear
//tp.operations[0].is_collinear = true;
//tp.operations[1].is_collinear = true;
//tp.method = method_touch_interior; // only because arrival != 0
BOOST_ASSERT(result.template get<0>().count > 1);
//geometry::convert(result.template get<0>().intersections[1], tp.point);
base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 1);
BOOST_ASSERT(inters.i_info().count > 1);
base_turn_handler::assign_point(tp, method_touch_interior,
inters.i_info(), 1);
AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>());
AssignPolicy::apply(tp, inters.pi(), inters.qi(),
inters.i_info(), inters.d_info());
}
tp.operations[0].operation = operation_blocked;
@@ -499,7 +468,7 @@ struct get_turn_info_linear_linear
res = true;
}
if ( is_q_spike && ( Version == append_touches || result.template get<1>().arrival[1] == 1 ) )
if ( is_q_spike && ( Version == append_touches || inters.d_info().arrival[1] == 1 ) )
{
if ( Version == append_touches )
{
@@ -512,12 +481,12 @@ struct get_turn_info_linear_linear
//tp.operations[0].is_collinear = true;
//tp.operations[1].is_collinear = true;
//tp.method = method_touch_interior; // only because arrival != 0
BOOST_ASSERT(result.template get<0>().count > 0);
//geometry::convert(result.template get<0>().intersections[0], tp.point);
base_turn_handler::assign_point(tp, method_touch_interior, result.template get<0>(), 0);
BOOST_ASSERT(inters.i_info().count > 0);
AssignPolicy::apply(tp, p1.first, q1.first, result.template get<0>(), result.template get<1>());
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
AssignPolicy::apply(tp, inters.pi(), inters.qi(),
inters.i_info(), inters.d_info());
}
tp.operations[0].operation = operation_intersection;