Boost-Geometry-Utils
view release on metacpan or search on metacpan
src/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp view on Meta::CPAN
int const side_qi_p = dir_info.sides.template get<index_q, 0>();
int const side_qk_p = SideStrategy::apply(pi, pj, qk);
if (side_qi_p == -side_qk_p)
{
// Q crosses P from left->right or from right->left (test "ML1")
// Union: folow P (left->right) or Q (right->left)
// Intersection: other turn
int index = side_qk_p == -1 ? index_p : index_q;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
return;
}
int const side_qk_q = SideStrategy::apply(qi, qj, qk);
if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)
{
// Q turns left on the right side of P (test "MR3")
// Both directions for "intersection"
both(ti, operation_intersection);
}
else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
{
// Q turns right on the left side of P (test "ML3")
// Union: take both operation
// Intersection: skip
both(ti, operation_union);
}
else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
{
// Q turns left on the left side of P (test "ML2")
// or Q turns right on the right side of P (test "MR2")
// Union: take left turn (Q if Q turns left, P if Q turns right)
// Intersection: other turn
int index = side_qk_q == 1 ? index_q : index_p;
ti.operations[index].operation = operation_union;
ti.operations[1 - index].operation = operation_intersection;
}
else if (side_qk_p == 0)
{
// Q intersects on interior of P and continues collinearly
if (side_qk_q == side_qi_p)
{
// Collinearly in the same direction
// (Q comes from left of P and turns left,
// OR Q comes from right of P and turns right)
// Omit intersection point.
// Union: just continue
// Intersection: just continue
both(ti, operation_continue);
}
else
{
// Opposite direction, which is never travelled.
// If Q turns left, P continues for intersection
// If Q turns right, P continues for union
ti.operations[Index].operation = side_qk_q == 1
? operation_intersection
: operation_union;
ti.operations[1 - Index].operation = operation_blocked;
}
}
else
{
// Should not occur!
ti.method = method_error;
}
}
};
template
<
typename TurnInfo,
typename SideStrategy
>
struct touch : public base_turn_handler
{
static inline bool between(int side1, int side2, int turn)
{
return side1 == side2 && ! opposite(side1, turn);
}
/*static inline void block_second(bool block, TurnInfo& ti)
{
if (block)
{
ti.operations[1].operation = operation_blocked;
}
}*/
template
<
typename Point1,
typename Point2,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
TurnInfo& ti,
IntersectionInfo const& intersection_info,
DirInfo const& dir_info)
{
ti.method = method_touch;
geometry::convert(intersection_info.intersections[0], ti.point);
int const side_qi_p1 = dir_info.sides.template get<1, 0>();
int const side_qk_p1 = SideStrategy::apply(pi, pj, qk);
// If Qi and Qk are both at same side of Pi-Pj,
// or collinear (so: not opposite sides)
if (! opposite(side_qi_p1, side_qk_p1))
{
int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
int const side_pk_p = SideStrategy::apply(pi, pj, pk);
int const side_qk_q = SideStrategy::apply(qi, qj, qk);
bool const both_continue = side_pk_p == 0 && side_qk_q == 0;
bool const robustness_issue_in_continue = both_continue && side_pk_q2 != 0;
bool const q_turns_left = side_qk_q == 1;
bool const block_q = side_qk_p1 == 0
&& ! same(side_qi_p1, side_qk_q)
&& ! robustness_issue_in_continue
;
// If Pk at same side as Qi/Qk
// (the "or" is for collinear case)
// or Q is fully collinear && P turns not to left
if (side_pk_p == side_qi_p1
|| side_pk_p == side_qk_p1
|| (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1)
)
{
// Collinear -> lines join, continue
// (#BRL2)
if (side_pk_q2 == 0 && ! block_q)
{
both(ti, operation_continue);
return;
}
int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
// Collinear opposite case -> block P
// (#BRL4, #BLR8)
if (side_pk_q1 == 0)
{
ti.operations[0].operation = operation_blocked;
// Q turns right -> union (both independent),
// Q turns left -> intersection
ti.operations[1].operation = block_q ? operation_blocked
: q_turns_left ? operation_intersection
: operation_union;
return;
}
// Pk between Qi and Qk
// (#BRL3, #BRL7)
if (between(side_pk_q1, side_pk_q2, side_qk_q))
{
ui_else_iu(q_turns_left, ti);
if (block_q)
{
ti.operations[1].operation = operation_blocked;
}
//block_second(block_q, ti);
return;
}
// Pk between Qk and P, so left of Qk (if Q turns right) and vv
// (#BRL1)
if (side_pk_q2 == -side_qk_q)
{
ui_else_iu(! q_turns_left, ti);
return;
}
//
// (#BRL5, #BRL9)
if (side_pk_q1 == -side_qk_q)
{
uu_else_ii(! q_turns_left, ti);
if (block_q)
{
ti.operations[1].operation = operation_blocked;
}
//block_second(block_q, ti);
return;
}
}
else
{
// Pk at other side than Qi/Pk
int const side_qk_q = SideStrategy::apply(qi, qj, qk);
bool const q_turns_left = side_qk_q == 1;
ti.operations[0].operation = q_turns_left
? operation_intersection
: operation_union;
ti.operations[1].operation = block_q
? operation_blocked
: side_qi_p1 == 1 || side_qk_p1 == 1
? operation_union
: operation_intersection;
return;
}
}
else
{
// From left to right or from right to left
int const side_pk_p = SideStrategy::apply(pi, pj, pk);
bool const right_to_left = side_qk_p1 == 1;
// If p turns into direction of qi (1,2)
if (side_pk_p == side_qi_p1)
{
int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
// Collinear opposite case -> block P
if (side_pk_q1 == 0)
{
ti.operations[0].operation = operation_blocked;
ti.operations[1].operation = right_to_left
? operation_union : operation_intersection;
return;
}
if (side_pk_q1 == side_qk_p1)
{
uu_else_ii(right_to_left, ti);
return;
}
}
// If p turns into direction of qk (4,5)
if (side_pk_p == side_qk_p1)
{
int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
// Collinear case -> lines join, continue
if (side_pk_q2 == 0)
{
both(ti, operation_continue);
return;
}
if (side_pk_q2 == side_qk_p1)
{
ui_else_iu(right_to_left, ti);
return;
}
}
// otherwise (3)
ui_else_iu(! right_to_left, ti);
return;
}
#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS
// Normally a robustness issue.
// TODO: more research if still occuring
std::cout << "Not yet handled" << std::endl
<< "pi " << get<0>(pi) << " , " << get<1>(pi)
<< " pj " << get<0>(pj) << " , " << get<1>(pj)
<< " pk " << get<0>(pk) << " , " << get<1>(pk)
<< std::endl
<< "qi " << get<0>(qi) << " , " << get<1>(qi)
<< " qj " << get<0>(qj) << " , " << get<1>(qj)
<< " qk " << get<0>(qk) << " , " << get<1>(qk)
<< std::endl;
#endif
}
};
template
<
typename TurnInfo,
typename SideStrategy
>
struct equal : public base_turn_handler
{
template
src/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp view on Meta::CPAN
{
use_p_for_union = true;
}
//std::cout << "ROBUSTNESS -> Collinear "
// << " arr: " << arrival
// << " dir: " << side_p << " " << side_q
// << " rev: " << side_pk << " " << side_qk
// << " cst: " << cside_p << " " << cside_q
// << std::boolalpha << " " << use_p_for_union
// << std::endl;
ui_else_iu(use_p_for_union, ti);
}
};
template
<
typename TurnInfo,
typename SideStrategy,
typename AssignPolicy
>
struct collinear_opposite : public base_turn_handler
{
private :
/*
arrival P arrival Q pk//p1 qk//q1 case result2 result
--------------------------------------------------------------
1 1 1 -1 CLO1 ix xu
1 1 1 0 CLO2 ix (xx)
1 1 1 1 CLO3 ix xi
1 1 0 -1 CCO1 (xx) xu
1 1 0 0 CCO2 (xx) (xx)
1 1 0 1 CCO3 (xx) xi
1 1 -1 -1 CRO1 ux xu
1 1 -1 0 CRO2 ux (xx)
1 1 -1 1 CRO3 ux xi
-1 1 -1 CXO1 xu
-1 1 0 CXO2 (xx)
-1 1 1 CXO3 xi
1 -1 1 CXO1 ix
1 -1 0 CXO2 (xx)
1 -1 -1 CXO3 ux
*/
template
<
int Index,
typename Point,
typename IntersectionInfo
>
static inline bool set_tp(Point const& ri, Point const& rj, Point const& rk,
TurnInfo& tp, IntersectionInfo const& intersection_info)
{
int const side_rk_r = SideStrategy::apply(ri, rj, rk);
operation_type blocked = operation_blocked;
switch(side_rk_r)
{
case 1 :
// Turning left on opposite collinear: intersection
tp.operations[Index].operation = operation_intersection;
break;
case -1 :
// Turning right on opposite collinear: union
tp.operations[Index].operation = operation_union;
break;
case 0 :
// No turn on opposite collinear: block, do not traverse
// But this "xx" is usually ignored, it is useless to include
// two operations blocked, so the whole point does not need
// to be generated.
// So return false to indicate nothing is to be done.
if (AssignPolicy::include_opposite)
{
tp.operations[Index].operation = operation_opposite;
blocked = operation_opposite;
}
else
{
return false;
}
break;
}
// The other direction is always blocked when collinear opposite
tp.operations[1 - Index].operation = blocked;
// If P arrives within Q, set info on P (which is done above, index=0),
// this turn-info belongs to the second intersection point, index=1
// (see e.g. figure CLO1)
geometry::convert(intersection_info.intersections[1 - Index], tp.point);
return true;
}
public:
template
<
typename Point1,
typename Point2,
typename OutputIterator,
typename IntersectionInfo,
typename DirInfo
>
static inline void apply(
Point1 const& pi, Point1 const& pj, Point1 const& pk,
Point2 const& qi, Point2 const& qj, Point2 const& qk,
// Opposite collinear can deliver 2 intersection points,
TurnInfo const& tp_model,
OutputIterator& out,
IntersectionInfo const& intersection_info,
DirInfo const& dir_info)
{
TurnInfo tp = tp_model;
tp.method = method_collinear;
// If P arrives within Q, there is a turn dependent on P
if (dir_info.arrival[0] == 1
&& set_tp<0>(pi, pj, pk, tp, intersection_info))
{
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
// If Q arrives within P, there is a turn dependent on Q
if (dir_info.arrival[1] == 1
&& set_tp<1>(qi, qj, qk, tp, intersection_info))
{
AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
*out++ = tp;
}
if (AssignPolicy::include_opposite)
{
// Handle cases not yet handled above
if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0)
|| (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0))
{
for (int i = 0; i < 2; i++)
{
tp.operations[i].operation = operation_opposite;
}
for (unsigned int i = 0; i < intersection_info.count; i++)
{
( run in 0.630 second using v1.01-cache-2.11-cpan-39bf76dae61 )