[get_turns] Make side calculation for linear endpoints clearer. Don't calculate unnecessary sides.

This commit is contained in:
Adam Wulkiewicz
2018-12-15 01:53:12 +01:00
parent 60d1f8fa28
commit ee4ebca3c6
2 changed files with 74 additions and 50 deletions

View File

@@ -225,6 +225,8 @@ private:
template <bool EnableFirst, bool EnableLast>
struct get_turn_info_for_endpoint
{
typedef std::pair<operation_type, operation_type> operations_pair;
BOOST_STATIC_ASSERT(EnableFirst || EnableLast);
template<typename UniqueSubRange1,
@@ -413,14 +415,11 @@ struct get_turn_info_for_endpoint
}
else if ( ip_j2 )
{
// TODO: find out why side is used with respect to non-segments
// (that is: range2.at(0) to range1.at(0), denoted as x)
int const side_pj_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(1));
int const side_pj_x = sides.apply(range2.at(0), range1.at(0), range1.at(1));
int const side_qk_x = sides.apply(range2.at(0), range1.at(0), range2.at(2));
int const side_pj_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(1));
int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_pj_q2, side_pj_x, side_qk_x);
operations_pair operations = operations_of_equal(side_pj_q2, side_pj_q1, side_qk_q1);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
@@ -468,11 +467,10 @@ struct get_turn_info_for_endpoint
else if ( ip_j2 )
{
int const side_pi_q2 = sides.apply(range2.at(1), range2.at(2), range1.at(0));
int const side_pi_x = sides.apply(range2.at(0), range1.at(1), range1.at(0));
int const side_qk_x = sides.apply(range2.at(0), range1.at(1), range2.at(2));
int const side_pi_q1 = sides.apply(range2.at(0), range2.at(1), range1.at(0));
int const side_qk_q1 = sides.apply(range2.at(0), range2.at(1), range2.at(2));
std::pair<operation_type, operation_type>
operations = operations_of_equal(side_pi_q2, side_pi_x, side_qk_x);
operations_pair operations = operations_of_equal(side_pi_q2, side_pi_q1, side_qk_q1);
// TODO: must the above be calculated?
// wouldn't it be enough to check if segments are collinear?
@@ -578,23 +576,24 @@ struct get_turn_info_for_endpoint
*out++ = tp;
}
static inline std::pair<operation_type, operation_type>
operations_of_equal(int side_1, int side_2, int side_3)
static inline operations_pair operations_of_equal(int side_px_q2,
int side_px_q1,
int side_qk_q1)
{
// If pk is collinear with qj-qk, they continue collinearly.
// This can be on either side of p1 (== q1), or collinear
// If px (pi or pj) is collinear with qj-qk (q2), they continue collinearly.
// This can be on either side of q1, or collinear
// The second condition checks if they do not continue
// oppositely
if ( side_1 == 0 && side_2 == side_3 )
if (side_px_q2 == 0 && side_px_q1 == side_qk_q1)
{
return std::make_pair(operation_continue, operation_continue);
}
// If they turn to same side (not opposite sides)
if ( ! base_turn_handler::opposite(side_2, side_3) )
if ( ! base_turn_handler::opposite(side_px_q1, side_qk_q1) )
{
// If pk is left of q2 or collinear: p: union, q: intersection
if ( side_1 != -1 )
// If px is left of q2 or collinear: p: union, q: intersection
if (side_px_q2 != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
@@ -607,7 +606,7 @@ struct get_turn_info_for_endpoint
{
// They turn opposite sides. If p turns left (or collinear),
// p: union, q: intersection
if ( side_2 != -1 )
if (side_px_q1 != -1 )
{
return std::make_pair(operation_union, operation_intersection);
}
@@ -618,16 +617,15 @@ struct get_turn_info_for_endpoint
}
}
static inline bool operations_both(
std::pair<operation_type, operation_type> const& operations,
operation_type const op)
static inline bool operations_both(operations_pair const& operations,
operation_type const op)
{
return operations.first == op && operations.second == op;
}
static inline bool operations_combination(
std::pair<operation_type, operation_type> const& operations,
operation_type const op1, operation_type const op2)
static inline bool operations_combination(operations_pair const& operations,
operation_type const op1,
operation_type const op2)
{
return ( operations.first == op1 && operations.second == op2 )
|| ( operations.first == op2 && operations.second == op1 );

View File

@@ -725,8 +725,6 @@ struct get_turn_info_linear_areal
}
else
{
method_type replaced_method = method_touch_interior;
// The code below should avoid using a side_calculator.
// Mainly because it is constructed with the wrong points.
// It should never be constructed other than pi,pj,pk / qi,qj,qk
@@ -735,33 +733,40 @@ struct get_turn_info_linear_areal
// (and that method can assign the operations, no need to return
// a pair, that is not done anywhere in all turns/operations)
// pi is the intersection point at qj or in the middle of q1
// so consider segments
// 1. pi at qj: qi-qj-pj and qi-qj-qk
// x: qi-qj, y: qj-qk, qz: qk
// 2. pi in the middle of q1: qi-pi-pj and qi-pi-qj
// x: qi-pi, y: pi-qj, qz: qj
// qi-pi, side the same as WRT q1
// pi-qj, side the same as WRT q1
// qj WRT q1 is 0
method_type replaced_method = method_none;
int side_pj_y = 0, side_pj_x = 0, side_qz_x = 0;
// 1. ip0 or pi at qj
if ( ip0.is_qj )
{
int const side_pj_q2 = sides.apply(range_q.at(1), range_q.at(2), range_p.at(1));
int const side_pj_x = sides.apply(range_q.at(0), range_p.at(0), range_p.at(1));
int const side_qk_x = sides.apply(range_q.at(0), range_p.at(0), range_q.at(2));
std::pair<operation_type, operation_type> operations
= get_info_e::operations_of_equal(side_pj_q2, side_pj_x, side_qk_x);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
replaced_method = method_touch;
side_pj_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(1)); // pj wrt q2
side_pj_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(1)); // pj wrt q1
side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
}
// 2. ip0 or pi in the middle of q1
else
{
int const side_pj_y = sides.apply(range_p.at(0), range_q.at(1), range_p.at(1));
int const side_pj_x = sides.apply(range_q.at(0), range_p.at(0), range_p.at(1));
int const side_qj_x = sides.apply(range_q.at(0), range_p.at(0), range_q.at(1));
std::pair<operation_type, operation_type> operations
= get_info_e::operations_of_equal(side_pj_y, side_pj_x, side_qj_x);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
replaced_method = method_touch_interior;
side_pj_y = sides.apply(range_q.at(0), range_q.at(1), range_p.at(1)); // pj wrt q1
side_pj_x = side_pj_y; // pj wrt q1
side_qz_x = 0; // qj wrt q1
}
std::pair<operation_type, operation_type> operations
= get_info_e::operations_of_equal(side_pj_y, side_pj_x, side_qz_x);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;
turn_transformer_ec<true> transformer(replaced_method);
transformer(tp);
}
@@ -797,12 +802,33 @@ struct get_turn_info_linear_areal
}
else //if ( result.template get<0>().count == 1 )
{
int const side_pi_q2 = sides.apply(range_q.at(1), range_q.at(2), range_p.at(0));
int const side_pi_x = sides.apply(range_q.at(0), range_p.at(1), range_p.at(0));
int const side_qk_x = sides.apply(range_q.at(0), range_p.at(1), range_q.at(2));
// pj is the intersection point at qj or in the middle of q1
// so consider segments
// 1. pj at qj: qi-qj-pi and qi-qj-qk
// x: qi-qj, y: qj-qk, qz: qk
// 2. pj in the middle of q1: qi-pj-pi and qi-pj-qj
// x: qi-pj, y: pj-qj, qz: qj
// qi-pj, the side is the same as WRT q1
// pj-qj, the side is the same as WRT q1
// side of qj WRT q1 is 0
int side_pi_y = 0, side_pi_x = 0, side_qz_x = 0;
// 1. ip0 or pj at qj
if ( ip0.is_qj )
{
side_pi_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(0)); // pi wrt q2
side_pi_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1
side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
}
// 2. ip0 or pj in the middle of q1
else
{
side_pi_y = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1
side_pi_x = side_pi_y; // pi wrt q1
side_qz_x = 0; // qj wrt q1
}
std::pair<operation_type, operation_type> operations
= get_info_e::operations_of_equal(side_pi_q2, side_pi_x, side_qk_x);
= get_info_e::operations_of_equal(side_pi_y, side_pi_x, side_qz_x);
tp.operations[0].operation = operations.first;
tp.operations[1].operation = operations.second;