mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
relate(L,L) handled G1 last range point boundary in the exterior of G2
This commit is contained in:
@@ -248,13 +248,13 @@ struct linear_linear
|
||||
|
||||
// TODO: turns must be sorted and followed only if it's possible to go out and in on the same point
|
||||
// for linear geometries union operation must be detected which I guess would be quite often
|
||||
std::sort(turns.begin(), turns.end(), turns::less_seg_dist_op<0,1,2,4,3,0,0>());
|
||||
std::sort(turns.begin(), turns.end(), turns::less_seg_dist_op<0,2,3,1,4,0,0>());
|
||||
|
||||
analyse_turns<0, 1>(res, turns.begin(), turns.end(),
|
||||
geometry1, geometry2,
|
||||
boundary_checker1, boundary_checker2);
|
||||
|
||||
std::sort(turns.begin(), turns.end(), turns::less_seg_dist_op<0,1,2,4,3,0,1>());
|
||||
std::sort(turns.begin(), turns.end(), turns::less_seg_dist_op<0,2,3,1,4,0,1>());
|
||||
|
||||
analyse_turns<1, 0>(res, turns.begin(), turns.end(),
|
||||
geometry2, geometry1,
|
||||
@@ -438,20 +438,27 @@ struct linear_linear
|
||||
|
||||
exit_watcher<point_type> exit_watcher;
|
||||
segment_watcher seg_watcher;
|
||||
bool last_union = false;
|
||||
|
||||
for ( TurnIt it = first ; it != last ; ++it )
|
||||
{
|
||||
overlay::operation_type op = it->operations[OpId].operation;
|
||||
|
||||
if ( op != overlay::operation_union
|
||||
&& op != overlay::operation_intersection
|
||||
&& op != overlay::operation_blocked )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
segment_identifier const& seg_id = it->operations[OpId].seg_id;
|
||||
segment_identifier const& other_id = it->operations[OtherOpId].seg_id;
|
||||
|
||||
bool first_in_range = seg_watcher.update(seg_id); // TODO: could be calculated only for i and u
|
||||
bool first_in_range = seg_watcher.update(seg_id);
|
||||
bool fake_enter_detected = false;
|
||||
|
||||
// handle possible exit
|
||||
if ( exit_watcher.is_exit_detected() &&
|
||||
( op == overlay::operation_union || op == overlay::operation_intersection
|
||||
|| op == overlay::operation_continue || op == overlay::operation_blocked ) )
|
||||
if ( exit_watcher.is_exit_detected() )
|
||||
{
|
||||
// real exit point - may be multiple
|
||||
// we know that we entered and now we exit
|
||||
@@ -471,6 +478,25 @@ struct linear_linear
|
||||
}
|
||||
}
|
||||
|
||||
if ( first_in_range && !fake_enter_detected && last_union )
|
||||
{
|
||||
BOOST_ASSERT(it != first);
|
||||
TurnIt prev = it;
|
||||
--prev;
|
||||
segment_identifier const& prev_seg_id = prev->operations[OpId].seg_id;
|
||||
|
||||
// if there is a boundary on the last point
|
||||
if ( boost::size(sub_geometry::get(geometry, prev_seg_id)) > 1
|
||||
&& boundary_checker.template is_boundary<boundary_back_explicit>
|
||||
(range::back(sub_geometry::get(geometry, prev_seg_id)), prev_seg_id) )
|
||||
{
|
||||
update_result<boundary, exterior, '0', reverse_result>(res);
|
||||
}
|
||||
}
|
||||
|
||||
// reset state
|
||||
last_union = (op == overlay::operation_union);
|
||||
|
||||
// i/i, i/x, i/u
|
||||
if ( op == overlay::operation_intersection )
|
||||
{
|
||||
@@ -568,6 +594,7 @@ struct linear_linear
|
||||
}
|
||||
}
|
||||
}
|
||||
// method other than crosses, check more conditions
|
||||
else
|
||||
{
|
||||
bool this_b =
|
||||
@@ -584,9 +611,13 @@ struct linear_linear
|
||||
other_boundary_checker.template is_boundary<boundary_any>(it->point, other_id);
|
||||
// it's also the boundary of the other geometry
|
||||
if ( other_b )
|
||||
{
|
||||
update_result<boundary, boundary, '0', reverse_result>(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_result<boundary, interior, '0', reverse_result>(res);
|
||||
}
|
||||
|
||||
// first IP on the last segment point - this means that the first point is outside
|
||||
if ( first_in_range && op_blocked )
|
||||
@@ -598,9 +629,6 @@ struct linear_linear
|
||||
update_result<boundary, exterior, '0', reverse_result>(res);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO symetric case
|
||||
// last IP and the first segment point -> last IP and op == union
|
||||
}
|
||||
// boundaries don't overlap
|
||||
else
|
||||
@@ -620,157 +648,163 @@ struct linear_linear
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( op == overlay::operation_continue )
|
||||
{
|
||||
//update_result<interior, interior, '1', reverse_result>(res);
|
||||
}
|
||||
}
|
||||
|
||||
// here, the possible exit is the real one
|
||||
// we know that we entered and now we exit
|
||||
if ( exit_watcher.is_exit_detected() )
|
||||
if ( exit_watcher.is_exit_detected() || last_union ) // THIS CHECK IS REDUNDANT
|
||||
{
|
||||
// for sure
|
||||
update_result<interior, exterior, '1', reverse_result>(res);
|
||||
|
||||
// TODO: check if the last point is indeed the boundary
|
||||
// For LS it's sufficient to check has_boundary
|
||||
update_result<boundary, exterior, '0', reverse_result>(res);
|
||||
BOOST_ASSERT(first != last);
|
||||
TurnIt prev = last;
|
||||
--prev;
|
||||
segment_identifier const& prev_seg_id = prev->operations[OpId].seg_id;
|
||||
|
||||
// if there is a boundary on the last point
|
||||
if ( boost::size(sub_geometry::get(geometry, prev_seg_id)) > 1
|
||||
&& boundary_checker.template is_boundary<boundary_back_explicit>
|
||||
(range::back(sub_geometry::get(geometry, prev_seg_id)), prev_seg_id) )
|
||||
{
|
||||
update_result<boundary, exterior, '0', reverse_result>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TurnIt>
|
||||
static inline void analyse_turns_simple(result & res,
|
||||
TurnIt first, TurnIt last,
|
||||
Geometry1 const& geometry1,
|
||||
Geometry2 const& geometry2,
|
||||
bool has_boundary1, bool has_boundary2)
|
||||
{
|
||||
for ( TurnIt it = first ; it != last ; ++it )
|
||||
{
|
||||
// 'i'
|
||||
if ( it->method == overlay::method_crosses )
|
||||
{
|
||||
res.template update<interior, interior, '0'>(); // always true
|
||||
res.template update<interior, exterior, '1'>(); // not always true
|
||||
res.template update<exterior, interior, '1'>(); // not always true
|
||||
}
|
||||
// 'e' 'c'
|
||||
else if ( it->method == overlay::method_equal
|
||||
|| it->method == overlay::method_collinear )
|
||||
{
|
||||
res.template update<interior, interior, '1'>(); // always true
|
||||
}
|
||||
// 't' 'm'
|
||||
else if ( it->method == overlay::method_touch
|
||||
|| it->method == overlay::method_touch_interior )
|
||||
{
|
||||
bool b = handle_boundary_point(res, *it, geometry1, geometry2, has_boundary1, has_boundary2);
|
||||
|
||||
if ( it->has(overlay::operation_union) )
|
||||
{
|
||||
if ( !b )
|
||||
res.template update<interior, interior, '0'>();
|
||||
if ( it->operations[0].operation == overlay::operation_union )
|
||||
res.template update<interior, exterior, '1'>();
|
||||
if ( it->operations[1].operation == overlay::operation_union )
|
||||
res.template update<exterior, interior, '1'>();
|
||||
}
|
||||
//template <typename TurnIt>
|
||||
//static inline void analyse_turns_simple(result & res,
|
||||
// TurnIt first, TurnIt last,
|
||||
// Geometry1 const& geometry1,
|
||||
// Geometry2 const& geometry2,
|
||||
// bool has_boundary1, bool has_boundary2)
|
||||
//{
|
||||
// for ( TurnIt it = first ; it != last ; ++it )
|
||||
// {
|
||||
// // 'i'
|
||||
// if ( it->method == overlay::method_crosses )
|
||||
// {
|
||||
// res.template update<interior, interior, '0'>(); // always true
|
||||
// res.template update<interior, exterior, '1'>(); // not always true
|
||||
// res.template update<exterior, interior, '1'>(); // not always true
|
||||
// }
|
||||
// // 'e' 'c'
|
||||
// else if ( it->method == overlay::method_equal
|
||||
// || it->method == overlay::method_collinear )
|
||||
// {
|
||||
// res.template update<interior, interior, '1'>(); // always true
|
||||
// }
|
||||
// // 't' 'm'
|
||||
// else if ( it->method == overlay::method_touch
|
||||
// || it->method == overlay::method_touch_interior )
|
||||
// {
|
||||
// bool b = handle_boundary_point(res, *it, geometry1, geometry2, has_boundary1, has_boundary2);
|
||||
//
|
||||
// if ( it->has(overlay::operation_union) )
|
||||
// {
|
||||
// if ( !b )
|
||||
// res.template update<interior, interior, '0'>();
|
||||
// if ( it->operations[0].operation == overlay::operation_union )
|
||||
// res.template update<interior, exterior, '1'>();
|
||||
// if ( it->operations[1].operation == overlay::operation_union )
|
||||
// res.template update<exterior, interior, '1'>();
|
||||
// }
|
||||
|
||||
if ( it->has(overlay::operation_intersection) )
|
||||
res.template update<interior, interior, '1'>();
|
||||
// if ( it->has(overlay::operation_intersection) )
|
||||
// res.template update<interior, interior, '1'>();
|
||||
|
||||
if ( it->has(overlay::operation_blocked) )
|
||||
if ( !b )
|
||||
res.template update<interior, interior, '0'>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// if ( it->has(overlay::operation_blocked) )
|
||||
// if ( !b )
|
||||
// res.template update<interior, interior, '0'>();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//}
|
||||
|
||||
template <typename Turn>
|
||||
static inline bool handle_boundary_point(result & res,
|
||||
Turn const& turn,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
bool has_boundary1, bool has_boundary2)
|
||||
{
|
||||
bool pt_on_boundary1 = has_boundary1 && equals_terminal_point(turn.point, geometry1);
|
||||
bool pt_on_boundary2 = has_boundary2 && equals_terminal_point(turn.point, geometry2);
|
||||
//template <typename Turn>
|
||||
//static inline bool handle_boundary_point(result & res,
|
||||
// Turn const& turn,
|
||||
// Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
// bool has_boundary1, bool has_boundary2)
|
||||
//{
|
||||
// bool pt_on_boundary1 = has_boundary1 && equals_terminal_point(turn.point, geometry1);
|
||||
// bool pt_on_boundary2 = has_boundary2 && equals_terminal_point(turn.point, geometry2);
|
||||
|
||||
if ( pt_on_boundary1 && pt_on_boundary2 )
|
||||
res.template update<boundary, boundary, '0'>();
|
||||
else if ( pt_on_boundary1 )
|
||||
res.template update<boundary, interior, '0'>();
|
||||
else if ( pt_on_boundary2 )
|
||||
res.template update<interior, boundary, '0'>();
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// if ( pt_on_boundary1 && pt_on_boundary2 )
|
||||
// res.template update<boundary, boundary, '0'>();
|
||||
// else if ( pt_on_boundary1 )
|
||||
// res.template update<boundary, interior, '0'>();
|
||||
// else if ( pt_on_boundary2 )
|
||||
// res.template update<interior, boundary, '0'>();
|
||||
// else
|
||||
// return false;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// TODO: replace with generic point_in_boundary working also for multilinestrings
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool equals_terminal_point(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return detail::equals::equals_point_point(point, range::front(geometry))
|
||||
|| detail::equals::equals_point_point(point, range::back(geometry));
|
||||
}
|
||||
//// TODO: replace with generic point_in_boundary working also for multilinestrings
|
||||
//template <typename Point, typename Geometry>
|
||||
//static inline bool equals_terminal_point(Point const& point, Geometry const& geometry)
|
||||
//{
|
||||
// return detail::equals::equals_point_point(point, range::front(geometry))
|
||||
// || detail::equals::equals_point_point(point, range::back(geometry));
|
||||
//}
|
||||
|
||||
static inline void handle_boundaries(result & res,
|
||||
Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
bool has_boundary1, bool has_boundary2)
|
||||
{
|
||||
int pig_front = detail::within::point_in_geometry(range::front(geometry1), geometry2);
|
||||
//static inline void handle_boundaries(result & res,
|
||||
// Geometry1 const& geometry1, Geometry2 const& geometry2,
|
||||
// bool has_boundary1, bool has_boundary2)
|
||||
//{
|
||||
// int pig_front = detail::within::point_in_geometry(range::front(geometry1), geometry2);
|
||||
|
||||
if ( has_boundary1 )
|
||||
{
|
||||
int pig_back = detail::within::point_in_geometry(range::back(geometry1), geometry2);
|
||||
// if ( has_boundary1 )
|
||||
// {
|
||||
// int pig_back = detail::within::point_in_geometry(range::back(geometry1), geometry2);
|
||||
|
||||
if ( pig_front > 0 || pig_back > 0 )
|
||||
res.template set<boundary, interior, '0'>();
|
||||
if ( pig_front == 0 || pig_back == 0 )
|
||||
res.template set<boundary, boundary, '0'>();
|
||||
if ( pig_front < 0 || pig_back < 0 )
|
||||
{
|
||||
res.template set<boundary, exterior, '0'>();
|
||||
res.template set<interior, exterior, '1'>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pig_front > 0 )
|
||||
res.template set<interior, interior, '0'>();
|
||||
else if ( pig_front == 0 )
|
||||
res.template set<interior, boundary, '0'>();
|
||||
else if ( pig_front < 0 )
|
||||
res.template set<interior, exterior, '0'>();
|
||||
}
|
||||
// if ( pig_front > 0 || pig_back > 0 )
|
||||
// res.template set<boundary, interior, '0'>();
|
||||
// if ( pig_front == 0 || pig_back == 0 )
|
||||
// res.template set<boundary, boundary, '0'>();
|
||||
// if ( pig_front < 0 || pig_back < 0 )
|
||||
// {
|
||||
// res.template set<boundary, exterior, '0'>();
|
||||
// res.template set<interior, exterior, '1'>();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if ( pig_front > 0 )
|
||||
// res.template set<interior, interior, '0'>();
|
||||
// else if ( pig_front == 0 )
|
||||
// res.template set<interior, boundary, '0'>();
|
||||
// else if ( pig_front < 0 )
|
||||
// res.template set<interior, exterior, '0'>();
|
||||
// }
|
||||
|
||||
pig_front = detail::within::point_in_geometry(range::front(geometry2), geometry1);
|
||||
// pig_front = detail::within::point_in_geometry(range::front(geometry2), geometry1);
|
||||
|
||||
if ( has_boundary2 )
|
||||
{
|
||||
int pig_back = detail::within::point_in_geometry(range::back(geometry2), geometry1);
|
||||
// if ( has_boundary2 )
|
||||
// {
|
||||
// int pig_back = detail::within::point_in_geometry(range::back(geometry2), geometry1);
|
||||
|
||||
if ( pig_front > 0 || pig_back > 0 )
|
||||
res.template set<interior, boundary, '0'>();
|
||||
if ( pig_front == 0 || pig_back == 0 )
|
||||
res.template set<boundary, boundary, '0'>();
|
||||
if ( pig_front < 0 || pig_back < 0 )
|
||||
{
|
||||
res.template set<exterior, boundary, '0'>();
|
||||
res.template set<exterior, interior, '1'>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pig_front > 0 )
|
||||
res.template set<interior, interior, '0'>();
|
||||
else if ( pig_front == 0 )
|
||||
res.template set<boundary, interior, '0'>();
|
||||
else if ( pig_front < 0 )
|
||||
res.template set<exterior, interior, '0'>();
|
||||
}
|
||||
}
|
||||
// if ( pig_front > 0 || pig_back > 0 )
|
||||
// res.template set<interior, boundary, '0'>();
|
||||
// if ( pig_front == 0 || pig_back == 0 )
|
||||
// res.template set<boundary, boundary, '0'>();
|
||||
// if ( pig_front < 0 || pig_back < 0 )
|
||||
// {
|
||||
// res.template set<exterior, boundary, '0'>();
|
||||
// res.template set<exterior, interior, '1'>();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if ( pig_front > 0 )
|
||||
// res.template set<interior, interior, '0'>();
|
||||
// else if ( pig_front == 0 )
|
||||
// res.template set<boundary, interior, '0'>();
|
||||
// else if ( pig_front < 0 )
|
||||
// res.template set<exterior, interior, '0'>();
|
||||
// }
|
||||
//}
|
||||
};
|
||||
|
||||
}} // namespace detail::relate
|
||||
|
||||
Reference in New Issue
Block a user