[buffer] change last fix by adding is_flat_start/end properties to pieces.

These marks are used to check if a turn is really inside the generated buffer,
or on the flat end (then it should be kept).
This will NOT YET work for one-sided buffers.
This commit is contained in:
Barend Gehrels 2017-11-08 17:47:46 +01:00
parent f6808f8277
commit 694299b7c7
5 changed files with 69 additions and 15 deletions

View File

@ -274,6 +274,9 @@ struct buffer_range
* pup: penultimate_point
*/
bool const mark_flat
= end_strategy.get_piece_type() == geometry::strategy::buffer::buffered_flat_end;
geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
bool first = true;
@ -318,6 +321,11 @@ struct buffer_range
collection.add_side_piece(*prev, *it, generated_side, first);
if (first && mark_flat)
{
collection.mark_flat_start();
}
penultimate_point = *prev;
ultimate_point = *it;
last_p1 = generated_side.front();
@ -331,6 +339,12 @@ struct buffer_range
first_p2 = generated_side.back();
}
}
if (mark_flat)
{
collection.mark_flat_end();
}
return result;
}
};
@ -956,11 +970,6 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
areal_tag
>::type::value;
bool const linear = boost::is_same
<
typename tag_cast<typename tag<GeometryInput>::type, linear_tag>::type,
linear_tag
>::type::value;
dispatch::buffer_inserter
<
@ -977,8 +986,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
robust_policy, intersection_strategy.get_side_strategy());
collection.get_turns();
collection.classify_turns(linear
&& end_strategy.get_piece_type() == strategy::buffer::buffered_flat_end);
collection.classify_turns();
if (BOOST_GEOMETRY_CONDITION(areal))
{
collection.check_remaining_points(distance_strategy);

View File

@ -217,6 +217,8 @@ struct buffered_piece_collection
// 2: half, not part of offsetted rings - part of robust ring
std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
#endif
bool is_flat_start;
bool is_flat_end;
bool is_convex;
bool is_monotonic_increasing[2]; // 0=x, 1=y
@ -245,6 +247,8 @@ struct buffered_piece_collection
, right_index(-1)
, last_segment_index(-1)
, offsetted_count(-1)
, is_flat_start(false)
, is_flat_end(false)
, is_convex(false)
, robust_min_comparable_radius(0)
, robust_max_comparable_radius(0)
@ -499,7 +503,7 @@ struct buffered_piece_collection
}
}
inline void classify_turns(bool linear_flat_end)
inline void classify_turns()
{
for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it)
@ -508,7 +512,7 @@ struct buffered_piece_collection
{
it->location = inside_buffer;
}
if (it->count_on_original_boundary > 0 && ! linear_flat_end)
if (it->count_on_original_boundary > 0)
{
it->location = inside_buffer;
}
@ -1233,6 +1237,24 @@ struct buffered_piece_collection
}
}
inline void mark_flat_start()
{
if (! m_pieces.empty())
{
piece& back = m_pieces.back();
back.is_flat_start = true;
}
}
inline void mark_flat_end()
{
if (! m_pieces.empty())
{
piece& back = m_pieces.back();
back.is_flat_end = true;
}
}
//-------------------------------------------------------------------------
inline void enrich()

View File

@ -422,6 +422,13 @@ class analyse_turn_wrt_piece
{
points[i] = piece.robust_ring[piece.offsetted_count + i];
}
// 3--offsetted outline--0
// | |
// left | | right
// | |
// 2===>==original===>===1
}
else if (helper_count == 3)
{
@ -445,12 +452,15 @@ class analyse_turn_wrt_piece
{
return analyse_on_offsetted;
}
if (comparator(point, points[1]) || comparator(point, points[2]))
if (comparator(point, points[1]))
{
// It lies on the corner of a helper segment. For linear buffer,
// on flat and, this point should not be deleted.
// But if it is NOT on a flat end it might be discarded
return analyse_on_original_boundary;
// On original, right corner
return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
}
if (comparator(point, points[2]))
{
// On original, left corner
return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary;
}
// Right side of the piece

View File

@ -155,6 +155,7 @@ void test_all()
test_one<linestring, polygon>("one_bend", one_bend, join_round, end_round, 35.5603, 1.5, 1.5);
test_one<linestring, polygon>("one_bend", one_bend, join_miter, end_round, 35.7601, 1.5, 1.5);
test_one<linestring, polygon>("two_bends", two_bends, join_round, end_round, 46.2995, 1.5, 1.5);
test_one<linestring, polygon>("two_bends", two_bends, join_round, end_flat, 39.235, 1.5, 1.5);
test_one<linestring, polygon>("two_bends", two_bends, join_round_by_divide, end_flat, 39.235, 1.5, 1.5);
test_one<linestring, polygon>("two_bends", two_bends, join_miter, end_flat, 39.513, 1.5, 1.5);
@ -303,6 +304,14 @@ void test_all()
test_one<linestring, polygon>("mysql_25662426a_5", mysql_25662426a, join_round32, end_round32, 266.8505, 5.0);
test_one<linestring, polygon>("mysql_25662426a_10", mysql_25662426a, join_round32, end_round32, 660.7355, 10.0);
test_one<linestring, polygon>("mysql_25662426a_05", mysql_25662426a, join_round32, end_flat, 26.8352, 0.5);
test_one<linestring, polygon>("mysql_25662426a_1", mysql_25662426a, join_round32, end_flat, 53.3411, 1.0);
test_one<linestring, polygon>("mysql_25662426a_2", mysql_25662426a, join_round32, end_flat, 97.3644, 2.0);
test_one<linestring, polygon>("mysql_25662426a_3", mysql_25662426a, join_round32, end_flat, 138.0697, 3.0);
test_one<linestring, polygon>("mysql_25662426a_4", mysql_25662426a, join_round32, end_flat, 181.5115, 4.0);
test_one<linestring, polygon>("mysql_25662426a_5", mysql_25662426a, join_round32, end_flat, 227.8325, 5.0);
test_one<linestring, polygon>("mysql_25662426a_10", mysql_25662426a, join_round32, end_flat, 534.1084, 10.0);
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
// Left
test_one<linestring, polygon>("mysql_25662426a_1", mysql_25662426a, join_round32, end_round32, 54.9018, 1.0, 0.0);

View File

@ -268,7 +268,12 @@ private :
typedef typename bg::point_type<ring_type>::type point_type;
std::ostringstream out;
out << piece.index << " (" << piece_type_char(piece.type) << ") " << piece.first_seg_id.segment_index << ".." << piece.last_segment_index - 1;
out << piece.index
<< (piece.is_flat_start ? " FS" : "")
<< (piece.is_flat_end ? " FE" : "")
<< " (" << piece_type_char(piece.type) << ") "
<< piece.first_seg_id.segment_index
<< ".." << piece.last_segment_index - 1;
point_type label_point = bg::return_centroid<point_type>(corner);
if ((piece.type == bg::strategy::buffer::buffered_concave