Merge branch 'develop' into feature/intvalid

This commit is contained in:
Barend Gehrels
2017-10-11 10:19:58 +02:00
8 changed files with 598 additions and 335 deletions

File diff suppressed because one or more lines are too long

View File

@@ -372,7 +372,7 @@ inline void assign_parents(Geometry1 const& geometry1,
}
// Version for one geometry (called by buffer)
// Version for one geometry (called by buffer/dissolve)
template
<
typename Geometry,

View File

@@ -41,7 +41,7 @@ struct is_self_turn_check<overlay_buffer>
};
template <>
struct is_self_turn_check<overlay_dissolve>
struct is_self_turn_check<overlay_dissolve_union>
{
template <typename Turn>
static inline bool apply(Turn const& turn)
@@ -50,6 +50,15 @@ struct is_self_turn_check<overlay_dissolve>
}
};
template <>
struct is_self_turn_check<overlay_dissolve_intersection>
{
template <typename Turn>
static inline bool apply(Turn const& turn)
{
return false;
}
};
template <overlay_type OverlayType, typename Turn>
bool is_self_turn(Turn const& turn)

View File

@@ -21,7 +21,8 @@ enum overlay_type
overlay_intersection,
overlay_difference,
overlay_buffer,
overlay_dissolve
overlay_dissolve_union,
overlay_dissolve_intersection
};
#ifndef DOXYGEN_NO_DETAIL
@@ -41,6 +42,17 @@ enum operation_type
template <overlay_type OverlayType>
struct operation_from_overlay
{
};
template <>
struct operation_from_overlay<overlay_union>
{
static const operation_type value = operation_union;
};
template <>
struct operation_from_overlay<overlay_buffer>
{
static const operation_type value = operation_union;
};
@@ -57,6 +69,19 @@ struct operation_from_overlay<overlay_difference>
static const operation_type value = operation_intersection;
};
template <>
struct operation_from_overlay<overlay_dissolve_union>
{
static const operation_type value = operation_union;
};
template <>
struct operation_from_overlay<overlay_dissolve_intersection>
{
static const operation_type value = operation_intersection;
};
}} // namespace detail::overlay
#endif //DOXYGEN_NO_DETAIL

View File

@@ -714,7 +714,9 @@ struct traversal
turn_operation_type const& start_op,
int start_op_index) const
{
if (OverlayType != overlay_buffer)
if (OverlayType != overlay_buffer
&& OverlayType != overlay_dissolve_union
&& OverlayType != overlay_dissolve_intersection)
{
return;
}
@@ -742,6 +744,9 @@ struct traversal
bool const correct
= ! start_turn.both(operation_union)
&& start_op.seg_id.source_index == other_op.seg_id.source_index
&& start_op.seg_id.multi_index == other_op.seg_id.multi_index
&& start_op.seg_id.ring_index == other_op.seg_id.ring_index
&& start_op.seg_id.segment_index == to_vertex_index;
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)

View File

@@ -62,7 +62,7 @@ public :
typename RobustPolicy,
typename Turns,
typename Rings,
typename TurnInfoMap,
typename TurnInfoMap,
typename Clusters,
typename Visitor
>

View File

@@ -110,50 +110,41 @@ public :
}
};
struct dissolve_overlay_visitor
{
public :
void print(char const* /*header*/)
{
}
template <typename Turns>
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/)
{
}
template <typename Turns>
void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/)
{
}
template <typename Turns>
void visit_turns(int , Turns const& ) {}
template <typename Clusters, typename Turns>
void visit_clusters(Clusters const& , Turns const& ) {}
template <typename Turns, typename Turn, typename Operation>
void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/)
{
}
template <typename Turns, typename Turn, typename Operation>
void visit_traverse_reject(Turns const& , Turn const& , Operation const& ,
detail::overlay::traverse_error_type )
{}
};
template <typename Geometry, typename GeometryOut>
struct dissolve_ring_or_polygon
{
template <typename RescalePolicy, typename OutputIterator, typename Strategy>
template <typename Turns>
static inline void clear(Turns& turns)
{
typedef typename boost::range_value<Turns>::type turn_type;
for (typename boost::range_iterator<Turns>::type
it = boost::begin(turns);
it != boost::end(turns);
++it)
{
turn_type& turn = *it;
turn.discarded = false;
turn.cluster_id = -1;
turn.has_colocated_both = false;
turn.switch_source = false;
turn.touch_only = false;
}
clear_visit_info(turns);
}
template
<
typename RescalePolicy, typename OutputIterator,
typename Strategy, typename Visitor
>
static inline OutputIterator apply(Geometry const& geometry,
RescalePolicy const& rescale_policy,
OutputIterator out,
Strategy const& strategy)
Strategy const& strategy,
Visitor& visitor)
{
typedef typename point_type<Geometry>::type point_type;
@@ -171,99 +162,106 @@ struct dissolve_ring_or_polygon
detail::overlay::assign_null_policy
>(geometry, strategy, rescale_policy, turns, policy);
// The dissolve process is not necessary if there are no turns at all
visitor.visit_turns(1, turns);
if (boost::size(turns) > 0)
{
typedef typename ring_type<Geometry>::type ring_type;
typedef std::vector<ring_type> out_vector;
out_vector rings;
typedef std::map
<
signed_size_type,
detail::overlay::cluster_info
> cluster_type;
cluster_type clusters;
dissolve_overlay_visitor visitor;
// Enrich/traverse the polygons twice: once for union...
typename Strategy::side_strategy_type const
side_strategy = strategy.get_side_strategy();
enrich_intersection_points<false, false, overlay_dissolve>(turns,
clusters, geometry, geometry, rescale_policy,
side_strategy);
detail::overlay::traverse
<
false, false,
Geometry, Geometry,
overlay_dissolve,
backtrack_for_dissolve<Geometry>
>::apply(geometry, geometry,
strategy, rescale_policy,
turns, rings, clusters, visitor);
clear_visit_info(turns);
// ... and for intersection
enrich_intersection_points<false, false, overlay_intersection>(turns,
clusters, geometry, geometry, rescale_policy,
side_strategy);
detail::overlay::traverse
<
false, false,
Geometry, Geometry,
overlay_intersection,
backtrack_for_dissolve<Geometry>
>::apply(geometry, geometry,
strategy, rescale_policy,
turns, rings, clusters, visitor);
std::map<ring_identifier, detail::overlay::ring_turn_info> map;
detail::overlay::get_ring_turn_info<overlay_dissolve>(map, turns, clusters);
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename Strategy::template area_strategy
<
point_type
>::type area_strategy_type;
typedef typename area_strategy_type::return_type area_result_type;
typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
std::map<ring_identifier, properties> selected;
detail::overlay::select_rings<overlay_dissolve>(geometry, map, selected, strategy);
// Add intersected rings
{
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
ring_identifier id(2, 0, -1);
for (typename boost::range_iterator<std::vector<ring_type> const>::type
it = boost::begin(rings);
it != boost::end(rings);
++it)
{
selected[id] = properties(*it, area_strategy);
id.multi_index++;
}
}
detail::overlay::assign_parents(geometry, rings, selected, strategy, true);
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
}
else
if (boost::size(turns) == 0)
{
// No self-turns, then add original geometry
GeometryOut g;
geometry::convert(geometry, g);
*out++ = g;
return out;
}
typedef typename ring_type<Geometry>::type ring_type;
typedef std::vector<ring_type> out_vector;
out_vector rings;
typedef std::map
<
signed_size_type,
detail::overlay::cluster_info
> cluster_type;
cluster_type clusters;
// Enrich/traverse the polygons twice: first for union...
typename Strategy::side_strategy_type const
side_strategy = strategy.get_side_strategy();
enrich_intersection_points<false, false, overlay_dissolve_union>(turns,
clusters, geometry, geometry, rescale_policy,
side_strategy);
visitor.visit_turns(2, turns);
visitor.visit_clusters(clusters, turns);
std::map<ring_identifier, overlay::ring_turn_info> turn_info_per_ring;
detail::overlay::traverse
<
false, false,
Geometry, Geometry,
overlay_dissolve_union,
backtrack_for_dissolve<Geometry>
>::apply(geometry, geometry,
strategy, rescale_policy,
turns, rings, turn_info_per_ring, clusters, visitor);
visitor.visit_turns(3, turns);
// ... and then for intersection
clear(turns);
enrich_intersection_points<false, false, overlay_dissolve_intersection>(turns,
clusters, geometry, geometry, rescale_policy,
side_strategy);
visitor.visit_turns(4, turns);
detail::overlay::traverse
<
false, false,
Geometry, Geometry,
overlay_dissolve_intersection,
backtrack_for_dissolve<Geometry>
>::apply(geometry, geometry,
strategy, rescale_policy,
turns, rings, turn_info_per_ring, clusters, visitor);
visitor.visit_turns(5, turns);
detail::overlay::get_ring_turn_info<overlay_dissolve_union>(turn_info_per_ring, turns, clusters);
typedef typename geometry::point_type<Geometry>::type point_type;
typedef typename Strategy::template area_strategy
<
point_type
>::type area_strategy_type;
typedef typename area_strategy_type::return_type area_result_type;
typedef detail::overlay::ring_properties<point_type, area_result_type> properties;
std::map<ring_identifier, properties> selected;
detail::overlay::select_rings<overlay_dissolve_union>(geometry, turn_info_per_ring, selected, strategy);
// Add intersected rings
{
area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>();
ring_identifier id(2, 0, -1);
for (typename boost::range_iterator<std::vector<ring_type> const>::type
it = boost::begin(rings);
it != boost::end(rings);
++it)
{
selected[id] = properties(*it, area_strategy);
id.multi_index++;
}
}
detail::overlay::assign_parents(geometry, rings, selected, strategy, true);
return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out);
}
};
@@ -343,13 +341,15 @@ inline OutputIterator dissolve_inserter(Geometry const& geometry,
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(geometry);
detail::overlay::overlay_null_visitor visitor;
return dispatch::dissolve
<
typename tag<Geometry>::type,
typename tag<GeometryOut>::type,
Geometry,
GeometryOut
>::apply(geometry, robust_policy, out, strategy);
>::apply(geometry, robust_policy, out, strategy, visitor);
}
/*!
@@ -396,6 +396,8 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St
concepts::check<geometry_out>();
detail::overlay::overlay_null_visitor visitor;
dispatch::dissolve
<
typename tag<Geometry>::type,
@@ -404,7 +406,7 @@ inline void dissolve(Geometry const& geometry, Collection& output_collection, St
geometry_out
>::apply(geometry, detail::no_rescale_policy(),
std::back_inserter(output_collection),
strategy);
strategy, visitor);
}
template

View File

@@ -38,9 +38,14 @@ namespace detail { namespace dissolve
template <typename Multi, typename GeometryOut>
struct dissolve_multi
{
template <typename RescalePolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Multi const& multi, RescalePolicy const& rescale_policy,
OutputIterator out, Strategy const& strategy)
template
<
typename RescalePolicy, typename OutputIterator,
typename Strategy, typename Visitor
>
static inline OutputIterator apply(Multi const& multi,
RescalePolicy const& rescale_policy, OutputIterator out,
Strategy const& strategy, Visitor& visitor)
{
typedef typename boost::range_value<Multi>::type polygon_type;
typedef typename boost::range_iterator<Multi const>::type iterator_type;
@@ -55,7 +60,8 @@ struct dissolve_multi
<
polygon_type,
GeometryOut
>::apply(*it, rescale_policy, std::back_inserter(step1), strategy);
>::apply(*it, rescale_policy, std::back_inserter(step1),
strategy, visitor);
}
// Step 2: remove mutual overlap