[dissolve] using preferred operations, they are now also used to determine

the order in which turns are traversed (first preferred).
This introduces a specific traverse umbrella class for dissolve
This commit is contained in:
Barend Gehrels
2018-01-03 17:36:13 +01:00
parent bb506996f9
commit 83f3920ab9
3 changed files with 140 additions and 9 deletions

View File

@@ -344,6 +344,60 @@ struct traversal_ring_creator
}
}
template <typename Rings>
void iterate_with_preference(std::size_t phase,
Rings& rings, std::size_t& finalized_ring_size,
typename Backtrack::state_type& state)
{
for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
{
turn_type const& turn = m_turns[turn_index];
if (turn.discarded || turn.blocked())
{
// Skip discarded and blocked turns
continue;
}
turn_operation_type const& op0 = turn.operations[0];
turn_operation_type const& op1 = turn.operations[1];
if (phase == 0)
{
if (! op0.enriched.prefer_start && ! op1.enriched.prefer_start)
{
// Not preferred, take next one
continue;
}
}
if (turn.both(operation_continue))
{
// Traverse only one turn, the one with the SMALLEST remaining distance
// to avoid skipping a turn in between, which can happen in rare cases
// (e.g. #130)
int const op_index
= op0.remaining_distance <= op1.remaining_distance ? 0 : 1;
traverse_with_operation(turn, turn_index, op_index,
rings, finalized_ring_size, state);
}
else
{
bool const forward = op0.enriched.prefer_start;
int op_index = forward ? 0 : 1;
int const increment = forward ? 1 : -1;
for (int i = 0; i < 2; i++, op_index += increment)
{
traverse_with_operation(turn, turn_index, op_index,
rings, finalized_ring_size, state);
}
}
}
}
private:
traversal_type m_trav;

View File

@@ -0,0 +1,82 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2018 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_DISSOLVE_TRAVERSE_HPP
#define BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_DISSOLVE_TRAVERSE_HPP
#include <cstddef>
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace dissolve
{
/*!
\brief Traverses through intersection points / geometries. This version
for dissolves calls traversal_ring_creator in two phases
\ingroup dissolve
*/
template <typename Backtrack>
class traverse
{
public :
template
<
typename Geometry,
typename IntersectionStrategy,
typename RobustPolicy,
typename Turns,
typename Rings,
typename TurnInfoMap,
typename Clusters,
typename Visitor
>
static inline void apply(Geometry const& geometry,
IntersectionStrategy const& intersection_strategy,
RobustPolicy const& robust_policy,
Turns& turns, Rings& rings,
TurnInfoMap& turn_info_map,
Clusters& clusters,
Visitor& visitor)
{
detail::overlay::traversal_ring_creator
<
false, false, overlay_dissolve,
Geometry, Geometry,
Turns, TurnInfoMap, Clusters,
IntersectionStrategy,
RobustPolicy, Visitor,
Backtrack
> trav(geometry, geometry, turns, turn_info_map, clusters,
intersection_strategy, robust_policy, visitor);
std::size_t finalized_ring_size = boost::size(rings);
typename Backtrack::state_type state;
for (std::size_t phase = 0; phase < 2; phase++)
{
trav.iterate_with_preference(phase, rings, finalized_ring_size, state);
}
}
};
}} // namespace detail::dissolve
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_ALGORITHMS_DISSOLVE_TRAVERSE_HPP

View File

@@ -44,6 +44,7 @@
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/extensions/algorithms/detail/overlay/dissolve_traverse.hpp>
namespace boost { namespace geometry
{
@@ -219,7 +220,7 @@ struct dissolve_ring_or_polygon
cluster_type clusters;
// Enrich/traverse the polygons twice: first for union...
// Enrich/traverse the polygons
typename Strategy::side_strategy_type const
side_strategy = strategy.get_side_strategy();
@@ -233,14 +234,8 @@ struct dissolve_ring_or_polygon
std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
detail::overlay::traverse
<
false, false,
Geometry, Geometry,
overlay_dissolve,
backtrack_for_dissolve<Geometry>
>::apply(geometry, geometry,
strategy, rescale_policy,
detail::dissolve::traverse<backtrack_for_dissolve<Geometry> >
::apply(geometry, strategy, rescale_policy,
turns, rings, turn_info_per_ring, clusters, visitor);
visitor.visit_turns(3, turns);