Skip to content

Commit 5ecece1

Browse files
committed
fix: consider clusters in turn_in_piece_visitor
1 parent 146cd0e commit 5ecece1

File tree

5 files changed

+81
-15
lines changed

5 files changed

+81
-15
lines changed

include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ struct buffered_piece_collection
466466
turn_in_piece_visitor
467467
<
468468
geometry::cs_tag_t<point_type>,
469-
turn_vector_type, piece_vector_type, DistanceStrategy, Strategy
470-
> visitor(m_turns, m_pieces, m_distance_strategy, m_strategy);
469+
turn_vector_type, cluster_type, piece_vector_type, DistanceStrategy, Strategy
470+
> visitor(m_turns, m_clusters, m_pieces, m_distance_strategy, m_strategy);
471471

472472
geometry::partition
473473
<

include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp

+48-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ template
3838
<
3939
typename CsTag,
4040
typename Turns,
41+
typename Clusters,
4142
typename Pieces,
4243
typename DistanceStrategy,
4344
typename UmbrellaStrategy
@@ -46,6 +47,7 @@ template
4647
class turn_in_piece_visitor
4748
{
4849
Turns& m_turns; // because partition is currently operating on const input only
50+
Clusters const& m_clusters;
4951
Pieces const& m_pieces; // to check for piece-type
5052
DistanceStrategy const& m_distance_strategy; // to check if point is on original or one_sided
5153
UmbrellaStrategy const& m_umbrella_strategy;
@@ -77,6 +79,44 @@ class turn_in_piece_visitor
7779
return false;
7880
}
7981

82+
// Returns true if the turn is part of a cluster, and one of the other turns in the same
83+
// cluster is involved in the same piece as the operations in the turn.
84+
template <typename Turn, typename Piece>
85+
inline bool skip_by_same_cluster(Turn const& turn, Piece const& piece) const
86+
{
87+
if (turn.cluster_id <= 0)
88+
{
89+
return false;
90+
}
91+
92+
auto it = m_clusters.find(turn.cluster_id);
93+
if (it == m_clusters.end())
94+
{
95+
return false;
96+
}
97+
98+
for (auto const& index : it->second.turn_indices)
99+
{
100+
if (index == turn.turn_index)
101+
{
102+
continue;
103+
}
104+
auto const& other_turn = m_turns[index];
105+
auto const& seg_id0 = other_turn.operations[0].seg_id;
106+
auto const& seg_id1 = other_turn.operations[1].seg_id;
107+
108+
if (seg_id0.piece_index == piece.index
109+
|| seg_id1.piece_index == piece.index)
110+
{
111+
// One of the other turns in the same cluster is an intersection
112+
// with the same piece.
113+
// Therefore, the turn under inspection cannot be within that piece.
114+
return true;
115+
}
116+
}
117+
return false;
118+
}
119+
80120
template <typename NumericType>
81121
inline bool is_one_sided(NumericType const& left, NumericType const& right) const
82122
{
@@ -96,10 +136,11 @@ class turn_in_piece_visitor
96136

97137
public:
98138

99-
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
139+
inline turn_in_piece_visitor(Turns& turns, Clusters const& clusters, Pieces const& pieces,
100140
DistanceStrategy const& distance_strategy,
101141
UmbrellaStrategy const& umbrella_strategy)
102142
: m_turns(turns)
143+
, m_clusters(clusters)
103144
, m_pieces(pieces)
104145
, m_distance_strategy(distance_strategy)
105146
, m_umbrella_strategy(umbrella_strategy)
@@ -140,7 +181,12 @@ class turn_in_piece_visitor
140181

141182
if (piece.type == geometry::strategy::buffer::buffered_empty_side)
142183
{
143-
return false;
184+
return true;
185+
}
186+
187+
if (skip_by_same_cluster(turn, piece))
188+
{
189+
return true;
144190
}
145191

146192
if (piece.type == geometry::strategy::buffer::buffered_point)

include/boost/geometry/algorithms/detail/overlay/overlay.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C
128128
turn_info_map[ring_id].has_blocked_turn = true;
129129
continue;
130130
}
131-
131+
132132
if (is_union && turn.any_blocked())
133133
{
134134
turn_info_map[ring_id].has_blocked_turn = true;

test/algorithms/buffer/buffer_cases.hpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,10 @@ static std::string const rt_w16
8282
static std::string const rt_w17
8383
= "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)))";
8484

85-
// Error in turn_in_piece, see readme
85+
// Needs checking turns of same cluster in turn_in_piece
8686
static std::string const rt_w18
8787
= "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)))";
8888

89-
9089
// Contains a cc turn (1) located wrongly.
9190
// Reported at 1/1, but should be 0/1 - or it should have a segment id belonging to previous segment.
9291
// Fixed by removing specific arriving handling.
@@ -102,6 +101,7 @@ static std::string const rt_w21
102101
= "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)))";
103102

104103
// Needs a spike. Also, it misses a small triangle, so area is not completely correct
104+
// Also, needs checking turns of same cluster in turn_in_piece
105105
static std::string const rt_w22
106106
= "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)))";
107107

@@ -157,4 +157,25 @@ static std::string const rt_w34
157157
static std::string const rt_w35
158158
= "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)))";
159159

160+
// Needs checking turns of same cluster in turn_in_piece
161+
// Also it has an interesting shape and several overlapping collinear borders in its rings.
162+
static std::string const rt_w36
163+
= "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)))";
164+
165+
// Needs checking turns of same cluster in turn_in_piece
166+
static std::string const rt_w37
167+
= "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)))";
168+
169+
// Needs checking turns of same cluster in turn_in_piece
170+
static std::string const rt_w38
171+
= "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)))";
172+
173+
// Needs checking turns of same cluster in turn_in_piece
174+
static std::string const rt_w39
175+
= "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)))";
176+
177+
// Needs checking turns of same cluster in turn_in_piece
178+
static std::string const rt_w40
179+
= "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)))";
180+
160181
#endif

test/algorithms/buffer/buffer_multi_polygon.cpp

+7-8
Original file line numberDiff line numberDiff line change
@@ -625,10 +625,7 @@ void test_all()
625625
TEST_BUFFER(rt_w15, join_miter, end_flat, 80.1348, 1.0);
626626
TEST_BUFFER(rt_w16, join_miter, end_flat, 31.6495, 1.0);
627627
TEST_BUFFER(rt_w17, join_miter, end_flat, 33.74264, 1.0);
628-
629-
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
630-
TEST_BUFFER(rt_w18, join_miter, end_flat, 82.4779, 1.0);
631-
#endif
628+
TEST_BUFFER(rt_w18, join_miter, end_flat, 83.4779, 1.0);
632629

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

638635
TEST_BUFFER(rt_w20, join_miter, end_flat, 63.0269, 1.0);
639636
TEST_BUFFER(rt_w21, join_miter, end_flat, 26.3137, 1.0);
640-
641-
#if defined(BOOST_GEOMETRY_TEST_FAILURES)
642-
TEST_BUFFER(rt_w22, join_miter, end_flat, 86.0416, 1.0);
643-
#endif
637+
TEST_BUFFER(rt_w22, join_miter, end_flat, 86.1274, 1.0);
644638

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

@@ -672,6 +666,11 @@ void test_all()
672666
TEST_BUFFER_VALIDITY_FALSE_NEGATIVE(rt_w35, join_round32, end_flat, 51.63174, 1.0);
673667

674668
TEST_BUFFER(rt_w35, join_miter, end_flat, 57.6569, 1.0);
669+
TEST_BUFFER(rt_w36, join_miter, end_flat, 60.1274, 1.0);
670+
TEST_BUFFER(rt_w37, join_miter, end_flat, 30.6569, 1.0);
671+
TEST_BUFFER(rt_w38, join_miter, end_flat, 68.2279, 1.0);
672+
TEST_BUFFER(rt_w39, join_miter, end_flat, 46.2279, 1.0);
673+
TEST_BUFFER(rt_w40, join_miter, end_flat, 49.0490, 1.0);
675674

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

0 commit comments

Comments
 (0)