summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/sections/sectionalize.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/sections/sectionalize.hpp')
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp194
1 files changed, 163 insertions, 31 deletions
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index 3ed5b8db07..f1d8e7d231 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013, 2014, 2015, 2017.
+// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -29,6 +29,8 @@
#include <boost/mpl/vector_c.hpp>
#include <boost/range.hpp>
#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
@@ -54,6 +56,7 @@
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/strategies/envelope.hpp>
namespace boost { namespace geometry
{
@@ -133,11 +136,21 @@ struct sections : std::vector<section<Box, DimensionCount> >
namespace detail { namespace sectionalize
{
+// NOTE: This utility will NOT work for latitudes, dimension 1 in spherical
+// and geographic coordinate system because in these coordinate systems
+// e.g. a segment on northern hemisphere may go towards greater latitude
+// and then towards lesser latitude.
template
<
+ typename Point,
typename DimensionVector,
std::size_t Index,
- std::size_t Count
+ std::size_t Count,
+ typename CastedCSTag = typename tag_cast
+ <
+ typename cs_tag<Point>::type,
+ spherical_tag
+ >::type
>
struct get_direction_loop
{
@@ -158,21 +171,67 @@ struct get_direction_loop
get_direction_loop
<
+ Point,
DimensionVector,
Index + 1,
- Count
+ Count,
+ CastedCSTag
+ >::apply(seg, directions);
+ }
+};
+
+template
+<
+ typename Point,
+ typename DimensionVector,
+ std::size_t Count
+>
+struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
+{
+ typedef typename boost::mpl::at_c<DimensionVector, 0>::type dimension;
+
+ template <typename Segment>
+ static inline void apply(Segment const& seg,
+ int directions[Count])
+ {
+ typedef typename coordinate_type<Segment>::type coordinate_type;
+ typedef typename coordinate_system<Point>::type::units units_t;
+
+ coordinate_type const diff = math::longitude_distance_signed
+ <
+ units_t, coordinate_type
+ >(geometry::get<0, 0>(seg),
+ geometry::get<1, 0>(seg));
+
+ coordinate_type zero = coordinate_type();
+ directions[0] = diff > zero ? 1 : diff < zero ? -1 : 0;
+
+ get_direction_loop
+ <
+ Point,
+ DimensionVector,
+ 1,
+ Count,
+ spherical_tag
>::apply(seg, directions);
}
};
-template <typename DimensionVector, std::size_t Count>
-struct get_direction_loop<DimensionVector, Count, Count>
+template
+<
+ typename Point,
+ typename DimensionVector,
+ std::size_t Count,
+ typename CastedCSTag
+>
+struct get_direction_loop<Point, DimensionVector, Count, Count, CastedCSTag>
{
template <typename Segment>
static inline void apply(Segment const&, int [Count])
{}
};
+
//! Copy one static array to another
template <typename T, std::size_t Index, std::size_t Count>
struct copy_loop
@@ -272,19 +331,21 @@ struct assign_loop<T, Count, Count>
template <typename CSTag>
struct box_first_in_section
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
- geometry::envelope(seg, box);
+ geometry::envelope(seg, box, strategy);
}
};
template <>
struct box_first_in_section<cartesian_tag>
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& )
{
geometry::envelope(prev, box);
geometry::expand(box, curr);
@@ -294,19 +355,21 @@ struct box_first_in_section<cartesian_tag>
template <typename CSTag>
struct box_next_in_section
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& prev, Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& prev, Point const& curr,
+ Strategy const& strategy)
{
geometry::model::referring_segment<Point const> seg(prev, curr);
- geometry::expand(box, seg);
+ geometry::expand(box, seg, strategy);
}
};
template <>
struct box_next_in_section<cartesian_tag>
{
- template <typename Box, typename Point>
- static inline void apply(Box & box, Point const& , Point const& curr)
+ template <typename Box, typename Point, typename Strategy>
+ static inline void apply(Box & box, Point const& , Point const& curr,
+ Strategy const& )
{
geometry::expand(box, curr);
}
@@ -335,6 +398,30 @@ struct sectionalize_part
ring_identifier ring_id,
std::size_t max_count)
{
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<typename Sections::box_type>::type
+ >::type envelope_strategy_type;
+
+ apply(sections, begin, end,
+ robust_policy, envelope_strategy_type(),
+ ring_id, max_count);
+ }
+
+ template
+ <
+ typename Iterator,
+ typename RobustPolicy,
+ typename Sections,
+ typename EnvelopeStrategy
+ >
+ static inline void apply(Sections& sections,
+ Iterator begin, Iterator end,
+ RobustPolicy const& robust_policy,
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
+ {
boost::ignore_unused_variable_warning(robust_policy);
typedef typename boost::range_value<Sections>::type section_type;
@@ -379,7 +466,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0};
get_direction_loop
<
- DimensionVector, 0, dimension_count
+ Point, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
@@ -449,14 +536,14 @@ struct sectionalize_part
// In cartesian this is envelope of previous point expanded with current point
// in non-cartesian this is envelope of a segment
box_first_in_section<typename cs_tag<robust_point_type>::type>
- ::apply(section.bounding_box, previous_robust_point, current_robust_point);
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
else
{
// In cartesian this is expand with current point
// in non-cartesian this is expand with a segment
box_next_in_section<typename cs_tag<robust_point_type>::type>
- ::apply(section.bounding_box, previous_robust_point, current_robust_point);
+ ::apply(section.bounding_box, previous_robust_point, current_robust_point, strategy);
}
section.end_index = index + 1;
@@ -501,11 +588,13 @@ struct sectionalize_range
<
typename Range,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Range const& range,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& strategy,
ring_identifier ring_id,
std::size_t max_count)
{
@@ -534,7 +623,7 @@ struct sectionalize_range
sectionalize_part<Point, DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
- robust_policy, ring_id, max_count);
+ robust_policy, strategy, ring_id, max_count);
}
};
@@ -549,12 +638,15 @@ struct sectionalize_polygon
<
typename Polygon,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Polygon const& poly,
RobustPolicy const& robust_policy,
Sections& sections,
- ring_identifier ring_id, std::size_t max_count)
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
{
typedef typename point_type<Polygon>::type point_type;
typedef sectionalize_range
@@ -564,7 +656,7 @@ struct sectionalize_polygon
> per_range;
ring_id.ring_index = -1;
- per_range::apply(exterior_ring(poly), robust_policy, sections, ring_id, max_count);
+ per_range::apply(exterior_ring(poly), robust_policy, sections, strategy, ring_id, max_count);
ring_id.ring_index++;
typename interior_return_type<Polygon const>::type
@@ -572,7 +664,7 @@ struct sectionalize_polygon
for (typename detail::interior_iterator<Polygon const>::type
it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
{
- per_range::apply(*it, robust_policy, sections, ring_id, max_count);
+ per_range::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@@ -584,11 +676,13 @@ struct sectionalize_box
<
typename Box,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(Box const& box,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& ,
ring_identifier const& ring_id, std::size_t max_count)
{
typedef typename point_type<Box>::type point_type;
@@ -613,12 +707,15 @@ struct sectionalize_box
points.push_back(lr);
points.push_back(ll);
+ // NOTE: Use cartesian envelope strategy in all coordinate systems
+ // because edges of a box are not geodesic segments
sectionalize_range
<
closed, false,
point_type,
DimensionVector
>::apply(points, robust_policy, sections,
+ strategy::envelope::cartesian_segment<>(),
ring_id, max_count);
}
};
@@ -630,11 +727,15 @@ struct sectionalize_multi
<
typename MultiGeometry,
typename RobustPolicy,
- typename Sections
+ typename Sections,
+ typename EnvelopeStrategy
>
static inline void apply(MultiGeometry const& multi,
RobustPolicy const& robust_policy,
- Sections& sections, ring_identifier ring_id, std::size_t max_count)
+ Sections& sections,
+ EnvelopeStrategy const& strategy,
+ ring_identifier ring_id,
+ std::size_t max_count)
{
ring_id.multi_index = 0;
for (typename boost::range_iterator<MultiGeometry const>::type
@@ -642,7 +743,7 @@ struct sectionalize_multi
it != boost::end(multi);
++it, ++ring_id.multi_index)
{
- Policy::apply(*it, robust_policy, sections, ring_id, max_count);
+ Policy::apply(*it, robust_policy, sections, strategy, ring_id, max_count);
}
}
};
@@ -814,14 +915,18 @@ template
typename DimensionVector,
typename Geometry,
typename Sections,
- typename RobustPolicy
+ typename RobustPolicy,
+ typename EnvelopeStrategy
>
inline void sectionalize(Geometry const& geometry,
RobustPolicy const& robust_policy,
Sections& sections,
+ EnvelopeStrategy const& strategy,
int source_index = 0,
std::size_t max_count = 10)
{
+ BOOST_STATIC_ASSERT((! boost::is_fundamental<EnvelopeStrategy>::value));
+
concepts::check<Geometry const>();
typedef typename boost::range_value<Sections>::type section_type;
@@ -855,12 +960,39 @@ inline void sectionalize(Geometry const& geometry,
Geometry,
Reverse,
DimensionVector
- >::apply(geometry, robust_policy, sections, ring_id, max_count);
+ >::apply(geometry, robust_policy, sections, strategy, ring_id, max_count);
detail::sectionalize::enlarge_sections(sections);
}
+template
+<
+ bool Reverse,
+ typename DimensionVector,
+ typename Geometry,
+ typename Sections,
+ typename RobustPolicy
+>
+inline void sectionalize(Geometry const& geometry,
+ RobustPolicy const& robust_policy,
+ Sections& sections,
+ int source_index = 0,
+ std::size_t max_count = 10)
+{
+ typedef typename strategy::envelope::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type
+ >::type envelope_strategy_type;
+
+ boost::geometry::sectionalize
+ <
+ Reverse, DimensionVector
+ >(geometry, robust_policy, sections,
+ envelope_strategy_type(),
+ source_index, max_count);
+}
+
}} // namespace boost::geometry