@@ -178,73 +178,89 @@ struct traverse_graph
178
178
bool continue_traverse (Ring& ring,
179
179
signed_size_type component_id,
180
180
signed_size_type start_node_id,
181
- signed_size_type current_node_id )
181
+ signed_size_type target_node_id )
182
182
{
183
- auto const current_turn_indices = get_turn_indices_by_node_id (m_turns, m_clusters,
184
- current_node_id, allow_closed);
185
-
186
- // Any valid node should always deliver at least one turn
187
- BOOST_ASSERT (! current_turn_indices.empty ());
183
+ signed_size_type current_node_id = target_node_id;
188
184
189
- auto const next_target_nodes = get_target_nodes<target_operation>(m_turns, m_clusters,
190
- current_turn_indices, component_id);
185
+ std::size_t iteration_count = 0 ;
191
186
192
- if (next_target_nodes.empty ())
187
+ // Keep traversing until it finds the start (successful finish), or it is stuck,
188
+ // or it find an already visited node during traversal.
189
+ // The iteration count is a defensive check to prevent endless loops and not iterate
190
+ // more than times there are turns (this should not happen).
191
+ while (iteration_count < m_turns.size ())
193
192
{
193
+ auto const current_turn_indices = get_turn_indices_by_node_id (m_turns, m_clusters,
194
+ current_node_id, allow_closed);
195
+
196
+ // Any valid node should always deliver at least one turn
197
+ BOOST_ASSERT (! current_turn_indices.empty ());
198
+
199
+ auto const next_target_nodes = get_target_nodes<target_operation>(m_turns, m_clusters,
200
+ current_turn_indices, component_id);
201
+
202
+ if (next_target_nodes.empty ())
203
+ {
194
204
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE_GRAPH)
195
- std::cout << " Stuck, start: " << start_node_id
196
- << " stuck: " << current_node_id
197
- << " (no targets) " << std::endl;
205
+ std::cout << " Stuck, start: " << start_node_id
206
+ << " stuck: " << current_node_id
207
+ << " (no targets) " << std::endl;
198
208
#endif
199
- return false ;
200
- }
209
+ return false ;
210
+ }
201
211
202
- auto const tois = get_tois<target_operation>(m_turns, m_clusters,
203
- current_node_id, next_target_nodes);
212
+ auto const tois = get_tois<target_operation>(m_turns, m_clusters,
213
+ current_node_id, next_target_nodes);
204
214
205
- if (tois.empty ())
206
- {
207
- return false ;
208
- }
215
+ if (tois.empty ())
216
+ {
217
+ return false ;
218
+ }
209
219
210
- auto const & turn_point = m_turns[*current_turn_indices.begin ()].point ;
220
+ auto const & turn_point = m_turns[*current_turn_indices.begin ()].point ;
211
221
212
- auto toi = *tois.begin ();
222
+ auto toi = *tois.begin ();
213
223
214
- if (tois.size () > 1 )
215
- {
216
- // Select the best target edge, using the last point of the ring and the turn point
217
- // for side calculations (if any).
218
- toi = m_edge_selector.select_target_edge (tois, ring.back (), turn_point);
219
- }
224
+ if (tois.size () > 1 )
225
+ {
226
+ // Select the best target edge, using the last point of the ring and the turn point
227
+ // for side calculations (if any).
228
+ toi = m_edge_selector.select_target_edge (tois, ring.back (), turn_point);
229
+ }
220
230
221
- if (m_visited_tois.count (toi) > 0 || m_finished_tois.count (toi) > 0 )
222
- {
231
+ if (m_visited_tois.count (toi) > 0 || m_finished_tois.count (toi) > 0 )
232
+ {
223
233
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE_GRAPH)
224
- std::cout << " ALREADY visited, turn " << toi
225
- << " in {" << current_node_id
226
- << " -> size " << next_target_nodes.size () << " }" << std::endl;
234
+ std::cout << " ALREADY visited, turn " << toi
235
+ << " in {" << current_node_id
236
+ << " -> size " << next_target_nodes.size () << " }" << std::endl;
227
237
#endif
228
- return false ;
229
- }
238
+ return false ;
239
+ }
230
240
231
- detail::overlay::append_no_collinear (ring, turn_point, m_strategy);
241
+ detail::overlay::append_no_collinear (ring, turn_point, m_strategy);
232
242
233
- set_visited (toi);
234
- use_vertices (ring, toi);
243
+ set_visited (toi);
244
+ use_vertices (ring, toi);
235
245
236
- auto const & selected_op = m_turns[toi.turn_index ].operations [toi.operation_index ];
237
- auto const next_target_node_id = get_node_id (m_turns,
238
- selected_op.enriched .travels_to_ip_index );
239
- if (next_target_node_id == start_node_id)
240
- {
246
+ auto const & selected_op = m_turns[toi.turn_index ].operations [toi.operation_index ];
247
+ auto const next_target_node_id = get_node_id (m_turns,
248
+ selected_op.enriched .travels_to_ip_index );
249
+ if (next_target_node_id == start_node_id)
250
+ {
241
251
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE_GRAPH)
242
- std::cout << " Finished at: " << next_target_node_id << std::endl;
252
+ std::cout << " Finished at: " << next_target_node_id << std::endl;
243
253
#endif
244
- return true ;
245
- }
254
+ return true ;
255
+ }
246
256
247
- return continue_traverse (ring, component_id, start_node_id, next_target_node_id);
257
+ current_node_id = next_target_node_id;
258
+ ++iteration_count;
259
+ }
260
+ #if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE_GRAPH)
261
+ std::cout << " Cancelled at: " << iteration_count << std::endl;
262
+ #endif
263
+ return false ;
248
264
}
249
265
250
266
template <typename Rings>
0 commit comments