[buffer] fix the case where a side was skipped because detected as equal, followed

by an end-cap. This caused further problems. Detection of empty sides is now delegated
to the strategy
This commit is contained in:
Barend Gehrels
2015-02-18 12:20:05 +01:00
parent 3c2a450742
commit 2201ebf86e
4 changed files with 87 additions and 71 deletions

View File

@@ -253,7 +253,6 @@ struct buffer_range
RobustPolicy
>::type robust_point_type;
robust_point_type previous_robust_input;
point_type second_point, penultimate_point, ultimate_point; // last two points from begin/end
/*
@@ -278,57 +277,50 @@ struct buffer_range
Iterator it = begin;
geometry::recalculate(previous_robust_input, *begin, robust_policy);
std::vector<output_point_type> generated_side;
generated_side.reserve(2);
for (Iterator prev = it++; it != end; ++it)
{
robust_point_type robust_input;
geometry::recalculate(robust_input, *it, robust_policy);
// Check on equality - however, if input is simplified, this is
// unlikely (though possible by rescaling or for degenerated pointlike polygons)
if (! detail::equals::equals_point_point(previous_robust_input, robust_input))
generated_side.clear();
side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
if (generated_side.empty())
{
generated_side.clear();
side_strategy.apply(*prev, *it, side,
distance_strategy, generated_side);
if (generated_side.empty())
{
break;
}
result = true;
if (! first)
{
add_join(collection,
penultimate_point,
*prev, last_p1, last_p2,
*it, generated_side.front(), generated_side.back(),
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
}
collection.add_side_piece(*prev, *it, generated_side, first);
penultimate_point = *prev;
ultimate_point = *it;
last_p1 = generated_side.front();
last_p2 = generated_side.back();
prev = it;
if (first)
{
first = false;
second_point = *it;
first_p1 = generated_side.front();
first_p2 = generated_side.back();
}
// Because input is simplified, this is improbable,
// but it can happen for degenerate geometries
// Further handling of this side is skipped
continue;
}
result = true;
if (! first)
{
add_join(collection,
penultimate_point,
*prev, last_p1, last_p2,
*it, generated_side.front(), generated_side.back(),
side,
distance_strategy, join_strategy, end_strategy,
robust_policy);
}
collection.add_side_piece(*prev, *it, generated_side, first);
penultimate_point = *prev;
ultimate_point = *it;
last_p1 = generated_side.front();
last_p2 = generated_side.back();
prev = it;
if (first)
{
first = false;
second_point = *it;
first_p1 = generated_side.front();
first_p2 = generated_side.back();
}
previous_robust_input = robust_input;
}
return result;
}

View File

@@ -805,11 +805,20 @@ struct buffered_piece_collection
inline void init_rescale_piece(piece& pc, std::size_t helper_points_size)
{
if (pc.first_seg_id.segment_index < 0)
{
// This indicates an error situation: an earlier piece was empty
// It currently does not happen
// std::cout << "EMPTY " << pc.type << " " << pc.index << " " << pc.first_seg_id.multi_index << std::endl;
pc.offsetted_count = 0;
return;
}
BOOST_ASSERT(pc.first_seg_id.multi_index >= 0);
BOOST_ASSERT(pc.last_segment_index >= 0);
pc.offsetted_count = pc.last_segment_index - pc.first_seg_id.segment_index;
BOOST_ASSERT(pc.offsetted_count >= 0);
BOOST_ASSERT(pc.first_seg_id.multi_index >= 0);
BOOST_ASSERT(pc.first_seg_id.segment_index >= 0);
BOOST_ASSERT(pc.last_segment_index >= 0);
pc.robust_ring.reserve(pc.offsetted_count + helper_points_size);
@@ -853,6 +862,11 @@ struct buffered_piece_collection
inline void calculate_robust_envelope(piece& pc)
{
if (pc.offsetted_count == 0)
{
return;
}
geometry::detail::envelope::envelope_range::apply(pc.robust_ring,
pc.robust_envelope);
@@ -879,6 +893,11 @@ struct buffered_piece_collection
const point_type& point3)
{
init_rescale_piece(pc, 3u);
if (pc.offsetted_count == 0)
{
return;
}
add_helper_point(pc, point1);
robust_point_type mid_point = add_helper_point(pc, point2);
add_helper_point(pc, point3);