[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 * 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; geometry::strategy::buffer::result_code result = geometry::strategy::buffer::result_no_output;
bool first = true; bool first = true;
@ -318,6 +321,11 @@ struct buffer_range
collection.add_side_piece(*prev, *it, generated_side, first); collection.add_side_piece(*prev, *it, generated_side, first);
if (first && mark_flat)
{
collection.mark_flat_start();
}
penultimate_point = *prev; penultimate_point = *prev;
ultimate_point = *it; ultimate_point = *it;
last_p1 = generated_side.front(); last_p1 = generated_side.front();
@ -331,6 +339,12 @@ struct buffer_range
first_p2 = generated_side.back(); first_p2 = generated_side.back();
} }
} }
if (mark_flat)
{
collection.mark_flat_end();
}
return result; 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, typename tag_cast<typename tag<GeometryInput>::type, areal_tag>::type,
areal_tag areal_tag
>::type::value; >::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 dispatch::buffer_inserter
< <
@ -977,8 +986,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
robust_policy, intersection_strategy.get_side_strategy()); robust_policy, intersection_strategy.get_side_strategy());
collection.get_turns(); collection.get_turns();
collection.classify_turns(linear collection.classify_turns();
&& end_strategy.get_piece_type() == strategy::buffer::buffered_flat_end);
if (BOOST_GEOMETRY_CONDITION(areal)) if (BOOST_GEOMETRY_CONDITION(areal))
{ {
collection.check_remaining_points(distance_strategy); 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 // 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 std::vector<point_type> helper_points; // 4 points for side, 3 points for join - 0 points for flat-end
#endif #endif
bool is_flat_start;
bool is_flat_end;
bool is_convex; bool is_convex;
bool is_monotonic_increasing[2]; // 0=x, 1=y bool is_monotonic_increasing[2]; // 0=x, 1=y
@ -245,6 +247,8 @@ struct buffered_piece_collection
, right_index(-1) , right_index(-1)
, last_segment_index(-1) , last_segment_index(-1)
, offsetted_count(-1) , offsetted_count(-1)
, is_flat_start(false)
, is_flat_end(false)
, is_convex(false) , is_convex(false)
, robust_min_comparable_radius(0) , robust_min_comparable_radius(0)
, robust_max_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 = for (typename boost::range_iterator<turn_vector_type>::type it =
boost::begin(m_turns); it != boost::end(m_turns); ++it) boost::begin(m_turns); it != boost::end(m_turns); ++it)
@ -508,7 +512,7 @@ struct buffered_piece_collection
{ {
it->location = inside_buffer; 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; 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() inline void enrich()

View File

@ -422,6 +422,13 @@ class analyse_turn_wrt_piece
{ {
points[i] = piece.robust_ring[piece.offsetted_count + i]; points[i] = piece.robust_ring[piece.offsetted_count + i];
} }
// 3--offsetted outline--0
// | |
// left | | right
// | |
// 2===>==original===>===1
} }
else if (helper_count == 3) else if (helper_count == 3)
{ {
@ -445,12 +452,15 @@ class analyse_turn_wrt_piece
{ {
return analyse_on_offsetted; 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 original, right corner
// on flat and, this point should not be deleted. return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary;
// But if it is NOT on a flat end it might be discarded }
return 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 // 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_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>("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, 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_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); 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_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_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) #if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
// Left // Left
test_one<linestring, polygon>("mysql_25662426a_1", mysql_25662426a, join_round32, end_round32, 54.9018, 1.0, 0.0); 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; typedef typename bg::point_type<ring_type>::type point_type;
std::ostringstream out; 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); point_type label_point = bg::return_centroid<point_type>(corner);
if ((piece.type == bg::strategy::buffer::buffered_concave if ((piece.type == bg::strategy::buffer::buffered_concave