mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-09 23:22:10 +00:00
Linestring/polygon overlay, phase 8 (difference)
[SVN r75682]
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
|
||||
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
|
||||
@@ -28,7 +29,7 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Follows a linestring from intersection point to intersection point, outputting which
|
||||
@@ -39,7 +40,8 @@ template
|
||||
<
|
||||
typename LineStringOut,
|
||||
typename LineString,
|
||||
typename Polygon
|
||||
typename Polygon,
|
||||
overlay_type OverlayType
|
||||
>
|
||||
class follow
|
||||
{
|
||||
@@ -119,7 +121,94 @@ class follow
|
||||
return false;
|
||||
}
|
||||
|
||||
// Template specialization structure to call the right actions for the right type
|
||||
template<overlay_type OverlayType>
|
||||
struct action_selector
|
||||
{
|
||||
// If you get here the overlay type is not intersection or difference
|
||||
BOOST_MPL_ASSERT(false);
|
||||
};
|
||||
|
||||
// Specialization for intersection, containing the implementation
|
||||
template<>
|
||||
struct action_selector<overlay_intersection>
|
||||
{
|
||||
template<typename OutputIterator, typename Point, typename Operation>
|
||||
static inline void enter(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, int index, Point const& point, Operation const& operation, OutputIterator& out)
|
||||
{
|
||||
// On enter, append the intersection point and remember starting point
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
segment_id = operation.seg_id;
|
||||
}
|
||||
|
||||
template<typename OutputIterator, typename Point, typename Operation>
|
||||
static inline void leave(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, int index, Point const& point, Operation const& operation, OutputIterator& out)
|
||||
{
|
||||
// On leave, copy all segments from starting point, append the intersection point
|
||||
// and add the output piece
|
||||
geometry::copy_segments<false>(linestring, segment_id, index, current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, point);
|
||||
if (! current_piece.empty())
|
||||
{
|
||||
*out++ = current_piece;
|
||||
current_piece.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_entered(bool entered)
|
||||
{
|
||||
return entered;
|
||||
}
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return geometry::within(point, geometry);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Specialization for difference, which reverses these actions
|
||||
template<>
|
||||
struct action_selector<overlay_difference>
|
||||
{
|
||||
typedef action_selector<overlay_intersection> normal_action;
|
||||
|
||||
template<typename OutputIterator, typename Point, typename Operation>
|
||||
static inline void enter(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, int index, Point const& point, Operation const& operation, OutputIterator& out)
|
||||
{
|
||||
normal_action::leave(current_piece, linestring, segment_id, index, point, operation, out);
|
||||
}
|
||||
|
||||
template<typename OutputIterator, typename Point, typename Operation>
|
||||
static inline void leave(LineStringOut& current_piece, LineString const& linestring, segment_identifier& segment_id, int index, Point const& point, Operation const& operation, OutputIterator& out)
|
||||
{
|
||||
normal_action::enter(current_piece, linestring, segment_id, index, point, operation, out);
|
||||
}
|
||||
|
||||
static inline bool is_entered(bool entered)
|
||||
{
|
||||
return ! normal_action::is_entered(entered);
|
||||
}
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return ! normal_action::included(point, geometry);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
public :
|
||||
|
||||
template <typename Point, typename Geometry>
|
||||
static inline bool included(Point const& point, Geometry const& geometry)
|
||||
{
|
||||
return action_selector<OverlayType>::included(point, geometry);
|
||||
}
|
||||
|
||||
template<typename Turns, typename OutputIterator>
|
||||
static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
|
||||
detail::overlay::operation_type operation,
|
||||
@@ -132,7 +221,6 @@ public :
|
||||
typename turn_type::container_type
|
||||
>::type turn_operation_iterator_type;
|
||||
|
||||
|
||||
// Sort intersection points on segments-along-linestring, and distance
|
||||
// (like in enrich is done for poly/poly)
|
||||
std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
|
||||
@@ -164,42 +252,33 @@ public :
|
||||
debug_traverse(*it, *iit, "-> Entering");
|
||||
|
||||
entered = true;
|
||||
detail::overlay::append_no_duplicates(current_piece, it->point);
|
||||
current_segment_id = iit->seg_id;
|
||||
action_selector<OverlayType>::enter(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
|
||||
}
|
||||
else if (is_leaving(*it, *iit, entered, first, linestring, polygon))
|
||||
{
|
||||
debug_traverse(*it, *iit, "-> Leaving");
|
||||
|
||||
entered = false;
|
||||
geometry::copy_segments<false>(linestring, current_segment_id,
|
||||
iit->seg_id.segment_index,
|
||||
current_piece);
|
||||
detail::overlay::append_no_duplicates(current_piece, it->point);
|
||||
|
||||
if (! current_piece.empty())
|
||||
{
|
||||
*out++ = current_piece;
|
||||
current_piece.clear();
|
||||
}
|
||||
action_selector<OverlayType>::leave(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (entered)
|
||||
if (action_selector<OverlayType>::is_entered(entered))
|
||||
{
|
||||
geometry::copy_segments<false>(linestring, current_segment_id,
|
||||
geometry::copy_segments<false>(linestring, current_segment_id,
|
||||
boost::size(linestring) - 1,
|
||||
current_piece);
|
||||
}
|
||||
|
||||
// Add the last one, if applicable
|
||||
// Output the last one, if applicable
|
||||
if (! current_piece.empty())
|
||||
{
|
||||
*out++ = current_piece;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
|
||||
#include <boost/geometry/views/segment_view.hpp>
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
|
||||
#include <boost/foreach.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
@@ -111,10 +114,18 @@ template
|
||||
typename LineString, typename Areal,
|
||||
bool ReverseAreal,
|
||||
typename OutputIterator, typename LineStringOut,
|
||||
overlay_type OverlayType,
|
||||
typename Strategy
|
||||
>
|
||||
struct intersection_of_linestring_with_areal
|
||||
{
|
||||
typedef detail::overlay::follow
|
||||
<
|
||||
LineStringOut,
|
||||
LineString,
|
||||
Areal,
|
||||
OverlayType
|
||||
> follower;
|
||||
|
||||
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
|
||||
template <typename Turn, typename Operation>
|
||||
@@ -150,14 +161,17 @@ struct intersection_of_linestring_with_areal
|
||||
detail::get_turns::no_interrupt_policy policy;
|
||||
geometry::get_turns
|
||||
<
|
||||
false, ReverseAreal, detail::overlay::calculate_distance_policy
|
||||
false,
|
||||
(OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
|
||||
detail::overlay::calculate_distance_policy
|
||||
>(linestring, areal, turns, policy);
|
||||
|
||||
if (turns.empty())
|
||||
{
|
||||
// No intersection points, it is either completely inside
|
||||
// No intersection points, it is either completely
|
||||
// inside (interior + borders)
|
||||
// or completely outside
|
||||
if (geometry::within(linestring[0], areal))
|
||||
if (follower::included(*boost::begin(linestring), areal))
|
||||
{
|
||||
LineStringOut copy;
|
||||
geometry::convert(linestring, copy);
|
||||
@@ -174,12 +188,7 @@ struct intersection_of_linestring_with_areal
|
||||
}
|
||||
#endif
|
||||
|
||||
return detail::overlay::follow
|
||||
<
|
||||
LineStringOut,
|
||||
LineString,
|
||||
Areal
|
||||
>::apply
|
||||
return follower::apply
|
||||
(
|
||||
linestring, areal,
|
||||
geometry::detail::overlay::operation_intersection,
|
||||
@@ -374,6 +383,7 @@ struct intersection_insert
|
||||
Linestring, Polygon,
|
||||
ReversePolygon,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
@@ -401,6 +411,7 @@ struct intersection_insert
|
||||
Linestring, Ring,
|
||||
ReverseRing,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
@@ -116,6 +116,7 @@ template
|
||||
typename MultiLinestring, typename Areal,
|
||||
bool ReverseAreal,
|
||||
typename OutputIterator, typename LineStringOut,
|
||||
overlay_type OverlayType,
|
||||
typename Strategy
|
||||
>
|
||||
struct intersection_of_multi_linestring_with_areal
|
||||
@@ -135,7 +136,7 @@ struct intersection_of_multi_linestring_with_areal
|
||||
<
|
||||
typename boost::range_value<MultiLinestring>::type,
|
||||
Areal, ReverseAreal,
|
||||
OutputIterator, LineStringOut, Strategy
|
||||
OutputIterator, LineStringOut, OverlayType, Strategy
|
||||
>::apply(*it, areal, out, strategy);
|
||||
}
|
||||
|
||||
@@ -150,6 +151,7 @@ template
|
||||
typename Areal, typename MultiLinestring,
|
||||
bool ReverseAreal,
|
||||
typename OutputIterator, typename LineStringOut,
|
||||
overlay_type OverlayType,
|
||||
typename Strategy
|
||||
>
|
||||
struct intersection_of_areal_with_multi_linestring
|
||||
@@ -162,6 +164,7 @@ struct intersection_of_areal_with_multi_linestring
|
||||
<
|
||||
MultiLinestring, Areal, ReverseAreal,
|
||||
OutputIterator, LineStringOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>::apply(ml, areal, out, strategy);
|
||||
}
|
||||
@@ -304,6 +307,7 @@ struct intersection_insert
|
||||
Linestring, MultiPolygon,
|
||||
ReverseMultiPolygon,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
@@ -333,6 +337,7 @@ struct intersection_insert
|
||||
Polygon, MultiLinestring,
|
||||
ReversePolygon,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
@@ -360,6 +365,7 @@ struct intersection_insert
|
||||
MultiLinestring, Ring,
|
||||
ReverseRing,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
@@ -389,6 +395,7 @@ struct intersection_insert
|
||||
MultiLinestring, MultiPolygon,
|
||||
ReverseMultiPolygon,
|
||||
OutputIterator, GeometryOut,
|
||||
OverlayType,
|
||||
Strategy
|
||||
>
|
||||
{};
|
||||
|
||||
Reference in New Issue
Block a user