Skip to content

Fix/buffer use cluster for within piece #1404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,8 @@ struct buffered_piece_collection
turn_in_piece_visitor
<
geometry::cs_tag_t<point_type>,
turn_vector_type, piece_vector_type, DistanceStrategy, Strategy
> visitor(m_turns, m_pieces, m_distance_strategy, m_strategy);
turn_vector_type, cluster_type, piece_vector_type, DistanceStrategy, Strategy
> visitor(m_turns, m_clusters, m_pieces, m_distance_strategy, m_strategy);

geometry::partition
<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ template
<
typename CsTag,
typename Turns,
typename Clusters,
typename Pieces,
typename DistanceStrategy,
typename UmbrellaStrategy
Expand All @@ -46,6 +47,7 @@ template
class turn_in_piece_visitor
{
Turns& m_turns; // because partition is currently operating on const input only
Clusters const& m_clusters;
Pieces const& m_pieces; // to check for piece-type
DistanceStrategy const& m_distance_strategy; // to check if point is on original or one_sided
UmbrellaStrategy const& m_umbrella_strategy;
Expand Down Expand Up @@ -77,6 +79,39 @@ class turn_in_piece_visitor
return false;
}

// Returns true if the turn is part of a cluster, and one of the other turns in the same
// cluster is involved in the same piece as the operations in the turn.
template <typename Turn, typename Piece>
inline bool skip_by_same_cluster(Turn const& turn, Piece const& piece) const
{
auto it = m_clusters.find(turn.cluster_id);
if (it == m_clusters.end())
{
return false;
}

for (auto const& index : it->second.turn_indices)
{
if (index == static_cast<signed_size_type>(turn.turn_index))
{
continue;
}
auto const& other_turn = m_turns[index];
auto const& seg_id0 = other_turn.operations[0].seg_id;
auto const& seg_id1 = other_turn.operations[1].seg_id;

if (seg_id0.piece_index == piece.index
|| seg_id1.piece_index == piece.index)
{
// One of the other turns in the same cluster is an intersection
// with the same piece.
// Therefore, the turn under inspection cannot be within that piece.
return true;
}
}
return false;
}

template <typename NumericType>
inline bool is_one_sided(NumericType const& left, NumericType const& right) const
{
Expand All @@ -96,10 +131,11 @@ class turn_in_piece_visitor

public:

inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
inline turn_in_piece_visitor(Turns& turns, Clusters const& clusters, Pieces const& pieces,
DistanceStrategy const& distance_strategy,
UmbrellaStrategy const& umbrella_strategy)
: m_turns(turns)
, m_clusters(clusters)
, m_pieces(pieces)
, m_distance_strategy(distance_strategy)
, m_umbrella_strategy(umbrella_strategy)
Expand Down Expand Up @@ -140,7 +176,12 @@ class turn_in_piece_visitor

if (piece.type == geometry::strategy::buffer::buffered_empty_side)
{
return false;
return true;
}

if (skip_by_same_cluster(turn, piece))
{
return true;
}

if (piece.type == geometry::strategy::buffer::buffered_point)
Expand Down
25 changes: 23 additions & 2 deletions test/algorithms/buffer/buffer_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,10 @@ static std::string const rt_w16
static std::string const rt_w17
= "MULTIPOLYGON(((3 1,4 2,4 1,3 1)),((5 3,6 4,6 3,5 3)),((5 0,5 1,6 1,6 0,5 0)),((8 5,9 6,9 5,8 5)),((8 5,7 4,7 5,8 5)))";

// Error in turn_in_piece, see readme
// Needs checking turns of same cluster in turn_in_piece
static std::string const rt_w18
= "MULTIPOLYGON(((4 4,4 5,5 4,4 4)),((5 6,6 7,6 6,5 6)),((5 1,4 1,4 2,5 3,5 1)),((7 6,7 7,8 7,7 6)),((0 6,1 6,1 5,1 4,0 4,0 6)),((1 8,2 7,1 7,1 8)),((1 8,2 9,2 8,1 8)),((1 6,1 7,2 6,1 6)),((7 3,7 2,6 2,7 3)),((7 3,7 4,8 4,8 3,7 3)),((3 2,3 1,2 1,3 2)),((3 2,2 2,2 3,3 3,3 2)),((5 8,5 7,4 7,4 8,5 8)),((5 8,6 9,6 8,5 8)))";


// Contains a cc turn (1) located wrongly.
// Reported at 1/1, but should be 0/1 - or it should have a segment id belonging to previous segment.
// Fixed by removing specific arriving handling.
Expand All @@ -102,6 +101,7 @@ static std::string const rt_w21
= "MULTIPOLYGON(((2 8,2 9,3 8,2 8)),((4 6,4 7,5 6,4 6)),((4 2,5 2,4 1,4 2)))";

// Needs a spike. Also, it misses a small triangle, so area is not completely correct
// Also, needs checking turns of same cluster in turn_in_piece
static std::string const rt_w22
= "MULTIPOLYGON(((6 3,6 4,7 4,7 3,6 3)),((6 1,6 2,7 2,6 1)),((2 8,2 9,3 9,2 8)),((4 7,5 8,5 7,4 7)),((2 1,2 0,1 0,2 1)),((2 1,2 2,3 2,3 1,2 1)),((3 3,2 2,2 3,3 3)),((3 3,3 4,4 3,3 3)),((0 5,1 4,1 3,0 3,0 5)),((8 6,9 6,9 5,8 5,8 6)),((8 6,7 6,6 6,7 7,8 6)),((1 3,1 2,0 2,1 3)),((4 3,5 3,4 2,4 3)),((4 2,5 1,4 1,4 2)))";

Expand Down Expand Up @@ -157,4 +157,25 @@ static std::string const rt_w34
static std::string const rt_w35
= "MULTIPOLYGON(((6 6,6 7,7 7,7 6,6 6)),((5 4,5 5,6 5,6 4,5 4)),((4 0,4 1,5 0,4 0)),((0 0,1 1,1 0,0 0)),((7 0,7 1,8 1,8 0,7 0)),((0 2,0 3,1 3,1 2,0 2)),((3 3,4 2,3 2,3 3)),((3 3,3 4,4 4,4 3,3 3)))";

// Needs checking turns of same cluster in turn_in_piece
// Also it has an interesting shape and several overlapping collinear borders in its rings.
static std::string const rt_w36
= "MULTIPOLYGON(((5 0,6 1,6 0,5 0)),((2 0,2 1,3 0,2 0)),((1 4,1 5,2 4,1 4)),((2 7,3 8,3 7,2 7)),((1 8,1 9,2 9,1 8)),((3 4,3 5,4 5,3 4)),((7.5 4.5,8 5,8 4,7 4,7 5,7.5 4.5)))";

// Needs checking turns of same cluster in turn_in_piece
static std::string const rt_w37
= "MULTIPOLYGON(((5 7,6 8,6 7,5 7)),((1 7,1 8,2 8,1 7)),((1 5,2 6,2 5,1 5)),((1 5,2 4,1 4,1 5)))";

// Needs checking turns of same cluster in turn_in_piece
static std::string const rt_w38
= "MULTIPOLYGON(((8 6,8 7,9 7,9 6,8 6)),((1 3,1 4,2 4,1 3)),((2 3,3 4,3 3,2 3)),((8 3,8 4,9 4,9 3,8 3)),((1 8,1 9,2 8,1 8)),((1 0,1 1,2 0,1 0)),((5 1,5 2,6 1,5 1)),((5 5,5 6,6 6,6 5,5 5)))";

// Needs checking turns of same cluster in turn_in_piece
static std::string const rt_w39
= "MULTIPOLYGON(((1 1,1 2,2 1,1 1)),((3 6,4 7,4 6,3 6)),((1 6,2 7,2 6,1 6)),((1 6,2 5,1 5,1 6)),((1 7,1 8,2 8,1 7)),((7 8,8 7,8 6,7 6,7 8)))";

// Needs checking turns of same cluster in turn_in_piece
static std::string const rt_w40
= "MULTIPOLYGON(((6 8,6 9,7 8,6 8)),((7 6,8 6,8 5,7 4,7 6)),((8 8,8 9,9 9,8 8)),((1 6,2 5,1 5,1 6)),((1 6,2 7,2 6,1 6)),((2 5,2 6,3 6,2 5)),((1 5,2 4,1 4,1 5)))";

#endif
8 changes: 5 additions & 3 deletions test/algorithms/buffer/buffer_linestring_geo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ void test_linestring_aimes()
std::set<int> const skip_cases_miter_flat{};
#else
// Cases where the algorithm is still failing.
std::set<int> const skip_cases_round_round{17, 22, 38, 181, 196};
std::set<int> const skip_cases_round_flat{17, 22, 38, 103, 196};
std::set<int> const skip_cases_miter_flat{17, 18, 22, 38, 103, 196};
// It might differ in debug/release mode.
// It might also depend on the compiler and on the operating system.
std::set<int> const skip_cases_round_round{17, 22, 38, 67, 75, 109, 163, 181, 143, 196};
std::set<int> const skip_cases_round_flat{17, 22, 38, 67, 75, 103, 109, 196};
std::set<int> const skip_cases_miter_flat{17, 18, 22, 38, 67, 75, 103, 109, 196};
#endif

for (auto const& enumerated : bg::util::enumerate(testcases_aimes))
Expand Down
15 changes: 7 additions & 8 deletions test/algorithms/buffer/buffer_multi_polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,10 +625,7 @@ void test_all()
TEST_BUFFER(rt_w15, join_miter, end_flat, 80.1348, 1.0);
TEST_BUFFER(rt_w16, join_miter, end_flat, 31.6495, 1.0);
TEST_BUFFER(rt_w17, join_miter, end_flat, 33.74264, 1.0);

#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w18, join_miter, end_flat, 82.4779, 1.0);
#endif
TEST_BUFFER(rt_w18, join_miter, end_flat, 83.4779, 1.0);

#if defined(BOOST_GEOMETRY_TEST_FAILURES) || defined(BOOST_GEOMETRY_CONCEPT_FIX_ARRIVAL)
// See comments at issue issue_1262
Expand All @@ -637,10 +634,7 @@ void test_all()

TEST_BUFFER(rt_w20, join_miter, end_flat, 63.0269, 1.0);
TEST_BUFFER(rt_w21, join_miter, end_flat, 26.3137, 1.0);

#if defined(BOOST_GEOMETRY_TEST_FAILURES)
TEST_BUFFER(rt_w22, join_miter, end_flat, 86.0416, 1.0);
#endif
TEST_BUFFER(rt_w22, join_miter, end_flat, 86.1274, 1.0);

TEST_BUFFER(rt_w23, join_miter, end_flat, 59.5711, 1.0);

Expand Down Expand Up @@ -672,6 +666,11 @@ void test_all()
TEST_BUFFER_VALIDITY_FALSE_NEGATIVE(rt_w35, join_round32, end_flat, 51.63174, 1.0);

TEST_BUFFER(rt_w35, join_miter, end_flat, 57.6569, 1.0);
TEST_BUFFER(rt_w36, join_miter, end_flat, 60.1274, 1.0);
TEST_BUFFER(rt_w37, join_miter, end_flat, 30.6569, 1.0);
TEST_BUFFER(rt_w38, join_miter, end_flat, 68.2279, 1.0);
TEST_BUFFER(rt_w39, join_miter, end_flat, 46.2279, 1.0);
TEST_BUFFER(rt_w40, join_miter, end_flat, 49.0490, 1.0);

test_one<multi_polygon_type, polygon_type>("nores_mt_1", nores_mt_1, join_round32, end_flat, 13.4113, 1.0);
test_one<multi_polygon_type, polygon_type>("nores_mt_2", nores_mt_2, join_round32, end_flat, 17.5265, 1.0);
Expand Down