mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 08:32:10 +00:00
Merge branch 'develop' into feature/intvalid
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -62,7 +62,7 @@ public :
|
||||
typename RobustPolicy,
|
||||
typename Turns,
|
||||
typename Rings,
|
||||
typename TurnInfoMap,
|
||||
typename TurnInfoMap,
|
||||
typename Clusters,
|
||||
typename Visitor
|
||||
>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user