mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-02 08:52:10 +00:00
[get_turns] Make side calculation for linear endpoints clearer. Don't calculate unnecessary sides.
This commit is contained in:
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user