Merge branch 'develop' of github.com:boostorg/geometry into develop

This commit is contained in:
Barend Gehrels
2014-04-26 14:49:51 +02:00
4 changed files with 285 additions and 323 deletions

View File

@@ -38,96 +38,115 @@ 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(pi(), 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(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;
}
result_type m_result;
side_calculator_type m_side_calc;
RobustPolicy const& m_robust_policy;
};
// SEGMENT_INTERSECTION RESULT
@@ -335,8 +354,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 +362,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 +378,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 +399,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 +410,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 +419,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 +450,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 +473,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 +513,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;

View File

@@ -335,7 +335,6 @@ void test_boxes(std::string const& wkt1, std::string const& wkt2, double expecte
}
}
template <typename P>
void test_point_output()
{
@@ -401,7 +400,6 @@ void test_areal_linear()
}
template <typename P>
void test_all()
{
@@ -563,6 +561,37 @@ void test_rational()
}
template <typename P>
void test_boxes_per_d(P const& min1, P const& max1, P const& min2, P const& max2, bool expected_result)
{
typedef bg::model::box<P> box;
box box_out;
bool detected = bg::intersection(box(min1, max1), box(min2, max2), box_out);
BOOST_CHECK_EQUAL(detected, expected_result);
if ( detected && expected_result )
{
BOOST_CHECK( bg::equals(box_out, box(min2,max1)) );
}
}
template <typename CoordinateType>
void test_boxes_nd()
{
typedef bg::model::point<CoordinateType, 1, bg::cs::cartesian> p1;
typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> p2;
typedef bg::model::point<CoordinateType, 3, bg::cs::cartesian> p3;
typedef bg::model::box<p1> b1;
typedef bg::model::box<p1> b2;
typedef bg::model::box<p1> b3;
test_boxes_per_d(p1(0), p1(5), p1(3), p1(6), true);
test_boxes_per_d(p2(0,0), p2(5,5), p2(3,3), p2(6,6), true);
test_boxes_per_d(p3(0,0,0), p3(5,5,5), p3(3,3,3), p3(6,6,6), true);
}
int test_main(int, char* [])
{
test_all<bg::model::d2::point_xy<double> >();
@@ -583,6 +612,8 @@ int test_main(int, char* [])
test_rational<bg::model::d2::point_xy<boost::rational<int> > >();
#endif
test_boxes_nd<double>();
return 0;
}