[buffer] fix check of buffer_flat_end for inside

This commit is contained in:
Barend Gehrels 2014-07-06 20:22:04 +02:00
parent da1323716a
commit b6b49f5308
5 changed files with 51 additions and 14 deletions

View File

@ -413,8 +413,9 @@ struct buffer_inserter<point_tag, Point, RingOutput>
RobustPolicy const& robust_policy)
{
collection.start_new_ring();
typedef detail::buffer::buffer_point<Point, RingOutput> base;
typedef detail::buffer::buffer_point<Point, RingOutput> base;
base::generate_circle(point, collection, distance, join_strategy, end_strategy, robust_policy);
collection.finish_ring();
}
};
@ -621,6 +622,7 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
strategy::buffer::buffer_side_right,
distance, side_strategy, join_strategy, end_strategy, robust_policy,
first_p1);
collection.finish_ring();
}
}
};
@ -663,6 +665,7 @@ private:
{
collection.start_new_ring();
policy::apply(*it, collection, distance, side_strategy, join_strategy, end_strategy, robust_policy);
collection.finish_ring();
}
}
@ -711,6 +714,7 @@ public:
collection.start_new_ring();
policy::apply(exterior_ring(polygon), collection,
distance, side_strategy, join_strategy, end_strategy, robust_policy);
collection.finish_ring();
}
apply_interior_rings(interior_rings(polygon),

View File

@ -118,6 +118,9 @@ struct buffered_piece_collection
strategy::buffer::piece_type type;
int index;
int left_index; // points to previous piece
int right_index; // points to next piece
// The next two members form together a complete clockwise ring
// for each piece (with one dupped point)
@ -139,6 +142,7 @@ struct buffered_piece_collection
piece_vector_type m_pieces;
turn_vector_type m_turns;
int m_first_piece_index;
buffered_ring_collection<buffered_ring<Ring> > offsetted_rings; // indexed by multi_index
std::vector< std::vector < robust_point_type > > robust_offsetted_rings;
@ -159,7 +163,8 @@ struct buffered_piece_collection
};
buffered_piece_collection(RobustPolicy const& robust_policy)
: m_robust_policy(robust_policy)
: m_first_piece_index(-1)
, m_robust_policy(robust_policy)
{}
@ -530,8 +535,8 @@ struct buffered_piece_collection
// Check if it is inside any of the pieces
turn_in_piece_visitor
<
turn_vector_type
> visitor(m_turns);
turn_vector_type, piece_vector_type
> visitor(m_turns, m_pieces);
geometry::partition
<
@ -559,6 +564,19 @@ struct buffered_piece_collection
current_segment_id.segment_index = 0;
offsetted_rings.resize(n + 1);
m_first_piece_index = boost::size(m_pieces);
}
inline void finish_ring()
{
BOOST_ASSERT(m_first_piece_index != -1);
// Reassign left-of-first and right-of-last
geometry::range::at(m_pieces, m_first_piece_index).left_index
= boost::size(m_pieces) - 1;
geometry::range::back(m_pieces).right_index = m_first_piece_index;
m_first_piece_index = -1;
}
inline int add_point(point_type const& p)
@ -582,6 +600,10 @@ struct buffered_piece_collection
pc.index = boost::size(m_pieces);
pc.first_seg_id = current_segment_id;
// Assign left/right (for first/last piece per ring they will be re-assigned later)
pc.left_index = pc.index - 1;
pc.right_index = pc.index + 1;
std::size_t const n = boost::size(offsetted_rings.back());
pc.first_seg_id.segment_index = decrease_segment_index_by_one ? n - 1 : n;

View File

@ -44,10 +44,12 @@ struct turn_ovelaps_box
return ! geometry::disjoint(box, turn.robust_point);
}
};
template <typename Turns>
template <typename Turns, typename Pieces>
class turn_in_piece_visitor
{
Turns& m_turns; // because partition is currently operating on const input only
Pieces const& m_pieces; // to check for piece-type
template <typename Point>
static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
@ -103,10 +105,12 @@ class turn_in_piece_visitor
return false;
}
public:
inline turn_in_piece_visitor(Turns& turns)
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces)
: m_turns(turns)
, m_pieces(pieces)
{}
template <typename Turn, typename Piece>
@ -133,9 +137,23 @@ public:
{
return;
}
typename boost::range_value<Pieces>::type const& pc
= m_pieces[turn.operations[i].piece_index];
if (pc.type == strategy::buffer::buffered_flat_end)
{
if (pc.left_index == piece.index
|| pc.right_index == piece.index)
{
// If it is a flat end, don't compare against its neighbor:
// it will always be located on one of the helper segments
return;
}
}
}
int geometry_code = detail::within::point_in_geometry(turn.robust_point, piece.robust_ring);
if (geometry_code == -1)
{
return;
@ -149,7 +167,6 @@ public:
// It is on the border but not on the offsetted ring.
// Then it is somewhere on the helper-segments
// Classify it as inside
// TODO: for neighbouring flat ends this does not apply
geometry_code = 1;
mutable_turn.count_on_helper++;
}

View File

@ -90,7 +90,6 @@ void test_all()
// Cases below should still be fixed because of remaining flat-end/inside bug
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
// Different cases with intersection points on flat and (left/right from line itself)
test_one<linestring, buf::join_round, buf::end_flat, polygon>("overlapping_asym_150_010", overlapping, 48.308, 1.5, 0.25);
test_one<linestring, buf::join_miter, buf::end_flat, polygon>("overlapping_asym_150_010", overlapping, 50.770, 1.5, 0.25);
@ -98,12 +97,11 @@ void test_all()
test_one<linestring, buf::join_miter, buf::end_flat, polygon>("overlapping_asym_150_075", overlapping, 60.985, 1.5, 0.75);
test_one<linestring, buf::join_round, buf::end_flat, polygon>("overlapping_asym_150_100", overlapping, 62.514, 1.5, 1.0);
test_one<linestring, buf::join_miter, buf::end_flat, polygon>("overlapping_asym_150_100", overlapping, 64.984, 1.5, 1.0);
#endif
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
// Having flat end
test_one<linestring, buf::join_round, buf::end_flat, polygon>("for_collinear", for_collinear, 68.561, 2.0, 2.0);
test_one<linestring, buf::join_miter, buf::end_flat, polygon>("for_collinear", for_collinear, 72, 2.0, 2.0);
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
test_one<linestring, buf::join_round, buf::end_flat, polygon>("for_collinear2", for_collinear2, 74.387, 2.0, 2.0);
test_one<linestring, buf::join_miter, buf::end_flat, polygon>("for_collinear2", for_collinear2, 78.0, 2.0, 2.0);
#endif

View File

@ -32,9 +32,7 @@ void test_all()
// Round joins / flat ends:
test_one<multi_linestring_type, buf::join_round, buf::end_flat, polygon>("simplex", simplex, 38.2623, 1.5, 1.5);
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
test_one<multi_linestring_type, buf::join_round, buf::end_flat, polygon>("two_bends", two_bends, 64.6217, 1.5, 1.5);
#endif
// TODO this should be fixed test_one<multi_linestring_type, buf::join_round, buf::end_flat, polygon>("turn_inside", turn_inside, 99, 1.5, 1.5);
test_one<multi_linestring_type, buf::join_round, buf::end_flat, polygon>("two_bends_asym", two_bends, 52.3793, 1.5, 0.75);
@ -43,10 +41,8 @@ void test_all()
// test_one<multi_linestring_type, buf::join_round, polygon>("turn_inside_asym_neg", turn_inside, 99, +1.5, -1.0);
// Miter / divide joins, various ends
#if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS)
test_one<multi_linestring_type, buf::join_round_by_divide, buf::end_flat, polygon>("two_bends", two_bends, 64.6217, 1.5, 1.5);
test_one<multi_linestring_type, buf::join_miter, buf::end_flat, polygon>("two_bends", two_bends, 65.1834, 1.5, 1.5);
#endif
test_one<multi_linestring_type, buf::join_miter, buf::end_round, polygon>("two_bends", two_bends, 75.2917, 1.5, 1.5);
}