diff --git a/include/boost/geometry/iterators/segment_iterator.hpp b/include/boost/geometry/iterators/segment_iterator.hpp new file mode 100644 index 000000000..e9747d55b --- /dev/null +++ b/include/boost/geometry/iterators/segment_iterator.hpp @@ -0,0 +1,277 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// specializations for points_begin + + +template +struct segments_begin +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(Linestring& linestring) + { + return result_type(linestring); + } +}; + + +template +struct segments_begin +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(Ring& ring) + { + return result_type(ring); + } +}; + + +template +struct segments_begin +{ + typedef typename detail_dispatch::point_iterator_inner_range_type + < + Polygon + >::type inner_range; + + typedef typename segment_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (segments_begin + < + inner_range + >::apply(geometry::exterior_ring(polygon)), + segments_end::apply(geometry::exterior_ring(polygon)), + flatten_iterator(boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon)) + ), + flatten_iterator(boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon)) + ) + ); + } +}; + + +template +struct segments_begin +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(MultiLinestring& multilinestring) + { + return result_type(boost::begin(multilinestring), + boost::end(multilinestring)); + } +}; + + +template +struct segments_begin +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(MultiPolygon& multipolygon) + { + return result_type(boost::begin(multipolygon), + boost::end(multipolygon)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +// specializations for points_end + + +template +struct segments_end +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(Linestring& linestring) + { + return result_type(linestring, true); + } +}; + + +template +struct segments_end +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(Ring& ring) + { + return result_type(ring, true); + } +}; + + +template +struct segments_end +{ + typedef typename detail_dispatch::point_iterator_inner_range_type + < + Polygon + >::type inner_range; + + typedef typename segment_iterator_type::type return_type; + + static inline return_type apply(Polygon& polygon) + { + typedef typename return_type::second_iterator_type flatten_iterator; + + return return_type + (segments_end::apply(geometry::exterior_ring(polygon)), + flatten_iterator(boost::begin(geometry::interior_rings(polygon)), + boost::end(geometry::interior_rings(polygon)) + ), + flatten_iterator( boost::end(geometry::interior_rings(polygon)) ) + ); + } +}; + + +template +struct segments_end +{ + typedef typename segment_iterator_type::type result_type; + + static inline result_type apply(MultiLinestring& multilinestring) + { + return result_type(boost::end(multilinestring)); + } +}; + + +template +struct segments_end +{ + typedef typename segment_iterator_type::type result_type; + static inline result_type apply(MultiPolygon& multipolygon) + { + return result_type(boost::end(multipolygon)); + } +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +// MK:: need to add doc here +template +class segment_iterator + : public dispatch::segment_iterator_type::type +{ +private: + typedef typename dispatch::segment_iterator_type::type base; + + base const* base_ptr() const + { + return this; + } + + template friend class segment_iterator; + + template + friend inline segment_iterator segments_begin(G const&); + + template + friend inline segment_iterator segments_end(G const&); + + segment_iterator(base const& base_it) : base(base_it) {} + +public: + segment_iterator() {} + + template + segment_iterator(segment_iterator const& other) + : base(*other.base_ptr()) + { + static const bool is_conv + = boost::is_convertible< + typename dispatch::segment_iterator_type + < + OtherGeometry const + >::type, + typename dispatch::segment_iterator_type::type + >::value; + + BOOST_MPL_ASSERT_MSG((is_conv), + NOT_CONVERTIBLE, + (segment_iterator)); + } +}; + + +// MK:: need to add doc here +template +inline segment_iterator +segments_begin(Geometry const& geometry) +{ + return dispatch::segments_begin::apply(geometry); +} + + +// MK:: need to add doc here +template +inline segment_iterator +segments_end(Geometry const& geometry) +{ + return dispatch::segments_end::apply(geometry); +} + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP