summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/length.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/length.hpp')
-rw-r--r--boost/geometry/algorithms/length.hpp161
1 files changed, 125 insertions, 36 deletions
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
index de53a39e8f..6cbec5303e 100644
--- a/boost/geometry/algorithms/length.hpp
+++ b/boost/geometry/algorithms/length.hpp
@@ -1,8 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2014.
+// Modifications copyright (c) 2014, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -16,18 +21,32 @@
#include <iterator>
+#include <boost/concept_check.hpp>
#include <boost/range.hpp>
+#include <boost/mpl/fold.hpp>
+#include <boost/mpl/greater.hpp>
#include <boost/mpl/if.hpp>
+#include <boost/mpl/insert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/transform.hpp>
#include <boost/type_traits.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+#include <boost/geometry/algorithms/detail/multi_sum.hpp>
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/views/closeable_view.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -43,9 +62,10 @@ namespace detail { namespace length
{
-template<typename Segment, typename Strategy>
+template<typename Segment>
struct segment_length
{
+ template <typename Strategy>
static inline typename default_length_result<Segment>::type apply(
Segment const& segment, Strategy const& strategy)
{
@@ -63,14 +83,16 @@ struct segment_length
\note for_each could be used here, now that point_type is changed by boost
range iterator
*/
-template<typename Range, typename Strategy, closure_selector Closure>
+template<typename Range, closure_selector Closure>
struct range_length
{
typedef typename default_length_result<Range>::type return_type;
+ template <typename Strategy>
static inline return_type apply(
Range const& range, Strategy const& strategy)
{
+ boost::ignore_unused_variable_warning(strategy);
typedef typename closeable_view<Range const, Closure>::type view_type;
typedef typename boost::range_iterator
<
@@ -106,35 +128,111 @@ namespace dispatch
{
-template <typename Tag, typename Geometry, typename Strategy>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct length : detail::calculate_null
- <
- typename default_length_result<Geometry>::type,
- Geometry,
- Strategy
- >
-{};
+{
+ typedef typename default_length_result<Geometry>::type return_type;
+ template <typename Strategy>
+ static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return calculate_null::apply<return_type>(geometry, strategy);
+ }
+};
-template <typename Geometry, typename Strategy>
-struct length<linestring_tag, Geometry, Strategy>
- : detail::length::range_length<Geometry, Strategy, closed>
+
+template <typename Geometry>
+struct length<Geometry, linestring_tag>
+ : detail::length::range_length<Geometry, closed>
{};
// RING: length is currently 0; it might be argued that it is the "perimeter"
-template <typename Geometry, typename Strategy>
-struct length<segment_tag, Geometry, Strategy>
- : detail::length::segment_length<Geometry, Strategy>
+template <typename Geometry>
+struct length<Geometry, segment_tag>
+ : detail::length::segment_length<Geometry>
{};
+template <typename MultiLinestring>
+struct length<MultiLinestring, multi_linestring_tag> : detail::multi_sum
+{
+ template <typename Strategy>
+ static inline typename default_length_result<MultiLinestring>::type
+ apply(MultiLinestring const& multi, Strategy const& strategy)
+ {
+ return multi_sum::apply
+ <
+ typename default_length_result<MultiLinestring>::type,
+ detail::length::range_length
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ closed // no need to close it explicitly
+ >
+ >(multi, strategy);
+
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_variant {
+
+template <typename Geometry>
+struct length
+{
+ template <typename Strategy>
+ static inline typename default_length_result<Geometry>::type
+ apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return dispatch::length<Geometry>::apply(geometry, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct length<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ typedef typename default_length_result
+ <
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
+ >::type result_type;
+
+ template <typename Strategy>
+ struct visitor
+ : static_visitor<result_type>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Geometry>
+ inline typename default_length_result<Geometry>::type
+ operator()(Geometry const& geometry) const
+ {
+ return length<Geometry>::apply(geometry, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline result_type apply(
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy
+ )
+ {
+ return apply_visitor(visitor<Strategy>(strategy), geometry);
+ }
+};
+
+} // namespace resolve_variant
+
+
/*!
\brief \brief_calc{length}
\ingroup length
@@ -147,24 +245,20 @@ struct length<segment_tag, Geometry, Strategy>
\qbk{[length] [length_output]}
*/
template<typename Geometry>
-inline typename default_length_result<Geometry>::type length(
- Geometry const& geometry)
+inline typename default_length_result<Geometry>::type
+length(Geometry const& geometry)
{
concept::check<Geometry const>();
// detail::throw_on_empty_input(geometry);
+ // TODO put this into a resolve_strategy stage
typedef typename strategy::distance::services::default_strategy
<
- point_tag, typename point_type<Geometry>::type
+ point_tag, point_tag, typename point_type<Geometry>::type
>::type strategy_type;
- return dispatch::length
- <
- typename tag<Geometry>::type,
- Geometry,
- strategy_type
- >::apply(geometry, strategy_type());
+ return resolve_variant::length<Geometry>::apply(geometry, strategy_type());
}
@@ -183,19 +277,14 @@ inline typename default_length_result<Geometry>::type length(
\qbk{[length_with_strategy] [length_with_strategy_output]}
*/
template<typename Geometry, typename Strategy>
-inline typename default_length_result<Geometry>::type length(
- Geometry const& geometry, Strategy const& strategy)
+inline typename default_length_result<Geometry>::type
+length(Geometry const& geometry, Strategy const& strategy)
{
concept::check<Geometry const>();
// detail::throw_on_empty_input(geometry);
-
- return dispatch::length
- <
- typename tag<Geometry>::type,
- Geometry,
- Strategy
- >::apply(geometry, strategy);
+
+ return resolve_variant::length<Geometry>::apply(geometry, strategy);
}